Skip to content
Open
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
43 changes: 26 additions & 17 deletions oks_cli/netpeering.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import ipaddress
import uuid
from subprocess import CalledProcessError

import os, sys
from .utils import cluster_completer, print_output, find_project_id_by_name, \
find_cluster_id_by_name, login_profile, ctx_update, \
profile_completer, project_completer, find_project_by_name, \
Expand Down Expand Up @@ -96,7 +96,7 @@ def netpeering_delete(ctx, netpeering_id, dry_run, force):
raise click.ClickException(f"Could not delete NetPeering {netpeering_id}: {e}")


def _gather_info(project: str=None, cluster: str=None) -> dict:
def load_environment(profile: str=None, project: str=None, cluster: str=None) -> dict:
"""
Gather information about project and cluster required to create a NetPeering
Set:
Expand All @@ -106,7 +106,9 @@ def _gather_info(project: str=None, cluster: str=None) -> dict:
- cluster_id
- project_cidr
"""

info = dict()
login_profile(profile)

if not project or not cluster:
raise click.ClickException("Project and cluster name are required")
Expand All @@ -115,6 +117,7 @@ def _gather_info(project: str=None, cluster: str=None) -> dict:
info.update({'cluster_name': cluster, 'project_name': project})
info.update({'project_id': project_data.get('id'), 'project_cidr': project_data.get('cidr')})
info.update({'cluster_id': find_cluster_id_by_name(info.get('project_id'), info.get('cluster_name'))})

return info


Expand Down Expand Up @@ -147,12 +150,10 @@ def _netpeering_exists(source: dict=None, target: dict=None, user: str=None, gro
return False


@netpeering.command('create', help="Create a NetPeering between 2 projects")
@click.option('--from-project', required=True, type=click.STRING, help="Source project name to create netpeering from")
@click.option('--from-cluster', required=True, type=click.STRING, help="Source cluster to create netpeering from")
@click.option('--to-project', required=True, type=click.STRING, help="Project name to create netpeering to")
@click.option('--to-cluster', required=True, type=click.STRING, help="Target cluster to create netpeering to")
@click.option('--netpeering-name', required=False, type=click.STRING, help="Name of the NetPeeringRequest, default to '{from-project}-to-{to-project}",
@netpeering.command('create')
@click.option("--source", required=True, type=click.STRING, metavar="<profile:project:cluster>", help="Source profile,project,cluster to create netpeering from. Profile can be omitted, in such case, 'default' or OKS_PROFILE will be used")
@click.option("--target", required=True, type=click.STRING, metavar="<profile:project:cluster>", help="Target profile,project,cluster to create netpeering to. Profile can be omitted, in such case, 'default' or OKS_PROFILE will be used")
@click.option('--netpeering-name', required=False, type=click.STRING, help="Name of the NetPeeringRequest, default to '{source-project}-to-{target-project}",
default=None)
@click.option('--auto-approve', required=False, is_flag=True, help="Automatically confirm NetPeering acceptance")
@click.option('--user', type=click.STRING, help="User")
Expand All @@ -161,14 +162,23 @@ def _netpeering_exists(source: dict=None, target: dict=None, user: str=None, gro
@click.option('--output', '-o', type=click.Choice(['json', 'yaml']), help="Specify output format, by default is json")
@click.option('--profile', help="Configuration profile to use", shell_complete=profile_completer)
@click.pass_context
def netpeering_create(ctx, from_project, from_cluster, to_project, to_cluster, netpeering_name, auto_approve,
def netpeering_create(ctx, source, target, netpeering_name, auto_approve,
user, group, dry_run, output, profile):
"""Create NetPeering between 2 projects"""
from_project, from_cluster, profile = ctx_update(ctx, from_project, from_cluster, profile)
login_profile(profile)
"""
Create NetPeering between 2 OKS projects.
Projects can be from the same profile or
from different profiles.
"""
if len(source.split(":")) != 3:
raise click.ClickException("--source must contains 3 parameters")
if len(target.split(":")) != 3:
raise click.ClickException("--target must contains 3 parameters")

source = _gather_info(project=from_project, cluster=from_cluster)
target = _gather_info(project=to_project, cluster=to_cluster)
[src_profile, src_project, src_cluster] = source.split(":")
[dst_profile, dst_project, dst_cluster] = target.split(":")

source = load_environment(profile=src_profile, project=src_project, cluster=src_cluster)
target = load_environment(profile=dst_profile, project=dst_project, cluster=dst_cluster)

source_cidr = ipaddress.ip_network(source.get('project_cidr'))
target_cidr = ipaddress.ip_network(target.get('project_cidr'))
Expand All @@ -182,14 +192,14 @@ def netpeering_create(ctx, from_project, from_cluster, to_project, to_cluster, n

# Ensure at least a nodepool is attached to the cluster
if len(source_nodepool.get('items')) == 0:
raise click.ClickException(f"Can't find nodepool in cluster {from_cluster}")
raise click.ClickException(f"Can't find nodepool in cluster {src_cluster}")

target_nodepool = json.loads(_run_kubectl(target.get('project_id'), target.get('cluster_id'), user, group,
['get', 'nodepool', '-o', 'json'], capture=True).stdout.decode('utf-8'))

# Ensure at least a nodepool is attached to the cluster
if len(target_nodepool.get('items')) == 0:
raise click.ClickException(f"Can't find nodepool in cluster {to_cluster}")
raise click.ClickException(f"Can't find nodepool in cluster {dst_cluster}")

source.update({'network_id': source_nodepool['items'][0]['metadata']['labels']['oks.network_id'],
'account_id': source_nodepool['items'][0]['metadata']['labels']['oks.account-id']})
Expand All @@ -199,7 +209,6 @@ def netpeering_create(ctx, from_project, from_cluster, to_project, to_cluster, n

if _netpeering_exists(source=source, target=target, user=user, group=group):
raise click.ClickException(f"A NetPeering already exists between projects {source.get('project_name')} and {target.get('project_name')}. Aborting!")

# Generate name
if not netpeering_name:
netpeering_name = f"{source.get('project_name')}-to-{target.get('project_name')}"
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ def add_default_profile():
}
}
profiles = json.dumps(profiles)
file.write(profiles)
file.write(profiles)
79 changes: 40 additions & 39 deletions tests/test_netpeering.py
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ def test_netpeering_get_peeringid_yaml_command(mock_request, mock_run, add_defau
"""

# Test the "netpeering create" command: verifies an error is thrown about overlaping networks
# netpeering create --from-project projectA --from-cluster clusterA \
# netpeering create --source "default:projectA:clusterA" \
# --to-project projectB --to-cluster clusterB \
# --netpeering-name testC --auto-approve

Expand All @@ -691,14 +691,14 @@ def test_netpeering_create_netoverlap_command(mock_request, add_default_profile)
runner = CliRunner()
result = runner.invoke(cli, ["netpeering", "-p", "projectA", "-c", "clusterA",
"create", "--netpeering-name", "test", "--auto-approve",
"--from-project", "projectA", "--from-cluster", "clusterA",
"--to-project", "projectB", "--to-cluster", "clusterB"])
"--source", "default:projectA:clusterA",
"--target", "default:projectB:clusterB"])
assert result.exit_code == 1
assert "Error: Source network 10.50.0.0/16 and target network 10.50.0.0/16 overlap, you can't create netpeering. Aborted!\n" in result.stderr

# Test the "netpeering create" command: verifies that source cluster without nodepool throws error
# netpeering create --from-project projectA --from-cluster clusterA \
# --to-project projectA --to-cluster clusterA \
# netpeering create --source "default:projectA:clusterA" \
# --target "default:projectB:clusterB" \
# --netpeering-name testC

@patch("oks_cli.utils.subprocess.run")
Expand Down Expand Up @@ -740,18 +740,19 @@ def test_netpeering_create_source_cluster_without_nodepool_fails_command(mock_re
runner = CliRunner()
result = runner.invoke(cli, ["netpeering", "-p", "projectA", "-c", "clusterA",
"create", "--netpeering-name", "test",
"--from-project", "projectA", "--from-cluster", "clusterA",
"--to-project", "projectB", "--to-cluster", "clusterB"])
"--source", "default:projectA:clusterA",
"--target", "default:projectB:clusterB"])
mock_run.assert_called()
args, kwargs = mock_run.call_args

assert result.exit_code == 1
assert ".oks_cli/cache/12345-12345/default/default/kubeconfig" in kwargs["env"]["KUBECONFIG"]
assert args[0] == ['kubectl', 'get', 'nodepool', '-o', 'json']
assert "Can't find nodepool in cluster clusterA" in result.stderr

# Test the "netpeering create" command: verifies that target cluster without nodepool throws error
# netpeering create --from-project projectA --from-cluster clusterA \
# --to-project projectA --to-cluster clusterA \
# netpeering create --source "default:projectA:clusterA" \
# --target "default:projectB:clusterB" \
# --netpeering-name testC

@patch("oks_cli.utils.subprocess.run")
Expand Down Expand Up @@ -828,8 +829,8 @@ def test_netpeering_create_target_cluster_without_nodepool_fails_command(mock_re
runner = CliRunner()
result = runner.invoke(cli, ["netpeering", "-p", "projectA", "-c", "clusterA",
"create", "--netpeering-name", "test",
"--from-project", "projectA", "--from-cluster", "clusterA",
"--to-project", "projectB", "--to-cluster", "clusterB"])
"--source", "default:projectA:clusterA",
"--target", "default:projectB:clusterB"])
mock_run.assert_called()
args, kwargs = mock_run.call_args
assert result.exit_code == 1
Expand All @@ -839,8 +840,8 @@ def test_netpeering_create_target_cluster_without_nodepool_fails_command(mock_re


# Test the "netpeering create" command: verifies that a NetPeering already exists
# netpeering create --from-project projectA --from-cluster clusterA \
# --to-project projectA --to-cluster clusterA \
# netpeering create --source "default:projectA:clusterA" \
# --target "default:projectB:clusterB" \
# --netpeering-name testC

@patch("oks_cli.utils.subprocess.run")
Expand Down Expand Up @@ -974,8 +975,8 @@ def test_netpeering_create_peering_exists_command(mock_request, mock_run, add_de
runner = CliRunner()
result = runner.invoke(cli, ["netpeering", "-p", "projectA", "-c", "clusterA",
"create", "--netpeering-name", "test",
"--from-project", "projectA", "--from-cluster", "clusterA",
"--to-project", "projectB", "--to-cluster", "clusterB"])
"--source", "default:projectA:clusterA",
"--target", "default:projectB:clusterB"])
mock_run.assert_called()
args, kwargs = mock_run.call_args
assert result.exit_code == 1
Expand All @@ -984,8 +985,8 @@ def test_netpeering_create_peering_exists_command(mock_request, mock_run, add_de
assert fake_response in result.output

# Test the "netpeering create" command: verifies that a NetPeering already exists
# netpeering create --from-project projectA --from-cluster clusterA \
# --to-project projectA --to-cluster clusterA \
# netpeering create --source "default:projectA:clusterA" \
# --target "default:projectB:clusterB" \
# --netpeering-name testC --dry-run

@patch("oks_cli.utils.subprocess.run")
Expand Down Expand Up @@ -1097,8 +1098,8 @@ def test_netpeering_create_dryrun_command(mock_request, mock_run, add_default_pr
runner = CliRunner()
result = runner.invoke(cli, ["netpeering", "-p", "projectA", "-c", "clusterA",
"create", "--netpeering-name", "mynetpeering-name",
"--from-project", "projectA", "--from-cluster", "clusterA",
"--to-project", "projectB", "--to-cluster", "clusterB", "--dry-run"])
"--source", "default:projectA:clusterA",
"--target", "default:projectB:clusterB", "--dry-run"])
mock_run.assert_called()
args, kwargs = mock_run.call_args
assert result.exit_code == 0
Expand All @@ -1111,8 +1112,8 @@ def test_netpeering_create_dryrun_command(mock_request, mock_run, add_default_pr
assert data.get("spec").get('accepterOwnerId') == "363338042637"

# Test the "netpeering create" command: verifies that a NetPeering fails because of an error during apply
# netpeering create --from-project projectA --from-cluster clusterA \
# --to-project projectA --to-cluster clusterA \
# netpeering create --source "default:projectA:clusterA" \
# --target "default:projectB:clusterB" \
# --netpeering-name testC

@patch("time.sleep")
Expand Down Expand Up @@ -1244,8 +1245,8 @@ def test_netpeering_create_requestexception_command(mock_request, mock_run, mock
runner = CliRunner()
result = runner.invoke(cli, ["netpeering", "-p", "projectA", "-c", "clusterA",
"create", "--netpeering-name", "mynetpeering-name",
"--from-project", "projectA", "--from-cluster", "clusterA",
"--to-project", "projectB", "--to-cluster", "clusterB"])
"--source", "default:projectA:clusterA",
"--target", "default:projectB:clusterB"])
mock_run.assert_called()
args, kwargs = mock_run.call_args
assert result.exit_code == 1
Expand All @@ -1254,8 +1255,8 @@ def test_netpeering_create_requestexception_command(mock_request, mock_run, mock
assert "Cannot create NetPeeringRequest:" in result.stderr

# Test the "netpeering create" command: verifies that a NetPeering state is in wrong state
# netpeering create --from-project projectA --from-cluster clusterA \
# --to-project projectA --to-cluster clusterA \
# netpeering create --source "default:projectA:clusterA \
# --target "default:projectB:clusterB \
# --netpeering-name testC

@patch("time.sleep")
Expand Down Expand Up @@ -1397,8 +1398,8 @@ def test_netpeering_create_netpeering_wrongstate_command(mock_request, mock_run,
runner = CliRunner()
result = runner.invoke(cli, ["netpeering", "-p", "projectA", "-c", "clusterA",
"create", "--netpeering-name", "mynetpeering-name",
"--from-project", "projectA", "--from-cluster", "clusterA",
"--to-project", "projectB", "--to-cluster", "clusterB"])
"--source", "default:projectA:clusterA",
"--target", "default:projectB:clusterB"])
mock_run.assert_called()
args, kwargs = mock_run.call_args
assert result.exit_code == 1
Expand All @@ -1407,8 +1408,8 @@ def test_netpeering_create_netpeering_wrongstate_command(mock_request, mock_run,
assert "NetPeeringAcceptance is in wrong state: wrong-state" in result.stderr

# Test the "netpeering create" command: verifies that a NetPeeringAcceptance fails
# netpeering create --from-project projectA --from-cluster clusterA \
# --to-project projectA --to-cluster clusterA \
# netpeering create --source "default:projectA:clusterA \
# --target "default:projectB:clusterB \
# --netpeering-name testC

@patch("time.sleep")
Expand Down Expand Up @@ -1558,8 +1559,8 @@ def test_netpeering_create_netpeeringacceptance_fails_command(mock_request, mock
runner = CliRunner()
result = runner.invoke(cli, ["netpeering", "-p", "projectA", "-c", "clusterA",
"create", "--netpeering-name", "mynetpeering-name", "--auto-approve",
"--from-project", "projectA", "--from-cluster", "clusterA",
"--to-project", "projectB", "--to-cluster", "clusterB"])
"--source", "default:projectA:clusterA",
"--target", "default:projectB:clusterB"])
mock_run.assert_called()
args, kwargs = mock_run.call_args
assert result.exit_code == 1
Expand All @@ -1568,8 +1569,8 @@ def test_netpeering_create_netpeeringacceptance_fails_command(mock_request, mock
assert "Error: Could not create NetPeeringAcceptance object" in result.stderr

# Test the "netpeering create" command: verifies that a NetPeering just created has a wrong-state
# netpeering create --from-project projectA --from-cluster clusterA \
# --to-project projectA --to-cluster clusterA \
# netpeering create --source "default:projectA:clusterA" \
# --target "default:projectB:clusterB" \
# --netpeering-name testC

@patch("time.sleep")
Expand Down Expand Up @@ -1779,8 +1780,8 @@ def test_netpeering_create_netpeering_checkstate_ok_command(mock_request, mock_r
runner = CliRunner()
result = runner.invoke(cli, ["netpeering", "-p", "projectA", "-c", "clusterA",
"create", "--netpeering-name", "mynetpeering-name", "--auto-approve",
"--from-project", "projectA", "--from-cluster", "clusterA",
"--to-project", "projectB", "--to-cluster", "clusterB"])
"--source", "default:projectA:clusterA",
"--target", "default:projectB:clusterB"])
mock_run.assert_called()
args, kwargs = mock_run.call_args
assert result.exit_code == 0
Expand All @@ -1790,8 +1791,8 @@ def test_netpeering_create_netpeering_checkstate_ok_command(mock_request, mock_r


# Test the "netpeering create" command: verifies that a when --auto-approve is not set, the netpeering request is deleted
# netpeering create --from-project projectA --from-cluster clusterA \
# --to-project projectA --to-cluster clusterA \
# netpeering create --source "default:projectA:clusterA" \
# --target "default:projectB:clusterB" \
# --netpeering-name testC

# @patch("time.sleep")
Expand Down Expand Up @@ -1943,8 +1944,8 @@ def test_netpeering_create_netpeering_checkstate_ok_command(mock_request, mock_r
# runner = CliRunner()
# result = runner.invoke(cli, ["netpeering", "-p", "projectA", "-c", "clusterA",
# "create", "--netpeering-name", "mynetpeering-name",
# "--from-project", "projectA", "--from-cluster", "clusterA",
# "--to-project", "projectB", "--to-cluster", "clusterB"])
# "--source", "default:projectA:clusterA",
# "--target", "default:projectB:clusterB"])
# mock_run.assert_called()
# args, kwargs = mock_run.call_args
# assert result.exit_code == 0
Expand Down