1# (c) 2017 Red Hat Inc.
2#
3# This file is part of Ansible
4#
5# Ansible is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# Ansible is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
17
18import pytest
19import os
20import collections
21from units.utils.amazon_placebo_fixtures import placeboify, maybe_sleep
22from ansible.modules.cloud.amazon import aws_direct_connect_link_aggregation_group as lag_module
23from ansible.module_utils.ec2 import get_aws_connection_info, boto3_conn
24
25
26@pytest.fixture(scope="module")
27def dependencies():
28
29    # each LAG dict will contain the keys: module, connections, virtual_interfaces
30    Dependencies = collections.namedtuple("Dependencies", ["lag_1", "lag_2"])
31    lag_1 = dict()
32    lag_2 = dict()
33
34    vanilla_params = {"name": "ansible_lag_1",
35                      "location": "EqSe2",
36                      "num_connections": 1,
37                      "min_links": 0,
38                      "bandwidth": "1Gbps"}
39
40    for lag in ("ansible_lag_1", "ansible_lag_2"):
41        params = dict(vanilla_params)
42        params["name"] = lag
43        if lag == "ansible_lag_1":
44            lag_1["module"] = FakeModule(**params)
45        else:
46            lag_2["module"] = FakeModule(**params)
47
48    if os.getenv("PLACEBO_RECORD"):
49        region, ec2_url, aws_connect_kwargs = get_aws_connection_info(lag_1["module"], boto3=True)
50        client = boto3_conn(lag_1["module"], conn_type="client", resource="directconnect", region=region, endpoint=ec2_url, **aws_connect_kwargs)
51        # See if link aggregation groups exist
52        for name in ("ansible_lag_1", "ansible_lag_2"):
53            lag_id = lag_module.create_lag(client, num_connections=1, location="EqSe2", bandwidth="1Gbps", name=name, connection_id=None)
54            if name == "ansible_lag_1":
55                lag_1["lag_id"] = lag_id
56                lag_1["name"] = name
57            else:
58                lag_2["lag_id"] = lag_id
59                lag_2["name"] = name
60        yield Dependencies(lag_1=lag_1, lag_2=lag_2)
61    else:
62        lag_1.update(lag_id="dxlag-fgkk4dja", name="ansible_lag_1")
63        lag_2.update(lag_id="dxlag-fgytkicv", name="ansible_lag_2")
64        yield Dependencies(lag_1=lag_1, lag_2=lag_2)
65
66    if os.getenv("PLACEBO_RECORD"):
67        # clean up
68        lag_module.ensure_absent(client, lag_1["lag_id"], lag_1["name"], True, True, True, 120)
69        lag_module.ensure_absent(client, lag_2["lag_id"], lag_2["name"], True, True, True, 120)
70
71
72class FakeModule(object):
73    def __init__(self, **kwargs):
74        self.params = kwargs
75
76    def fail_json(self, *args, **kwargs):
77        self.exit_args = args
78        self.exit_kwargs = kwargs
79        raise Exception("FAIL")
80
81    def exit_json(self, *args, **kwargs):
82        self.exit_args = args
83        self.exit_kwargs = kwargs
84
85
86def test_nonexistent_lag_status(placeboify, maybe_sleep):
87    client = placeboify.client("directconnect")
88    exists = lag_module.lag_exists(client=client,
89                                   lag_id="doesntexist",
90                                   lag_name="doesntexist",
91                                   verify=True)
92    assert not exists
93
94
95def test_lag_status(placeboify, maybe_sleep, dependencies):
96    client = placeboify.client("directconnect")
97    status = lag_module.lag_status(client, lag_id=dependencies.lag_1.get("lag_id"))
98    assert status.get("lagId") == dependencies.lag_1.get("lag_id")
99    assert status.get("lagName") == "ansible_lag_1"
100
101
102def test_lag_exists(placeboify, maybe_sleep, dependencies):
103    client = placeboify.client("directconnect")
104    exists = lag_module.lag_exists(client=client,
105                                   lag_id=dependencies.lag_1.get("lag_id"),
106                                   lag_name=None,
107                                   verify=True)
108    assert exists
109
110
111def test_lag_exists_using_name(placeboify, maybe_sleep, dependencies):
112    client = placeboify.client("directconnect")
113    exists = lag_module.lag_exists(client=client,
114                                   lag_id=None,
115                                   lag_name=dependencies.lag_1.get("name"),
116                                   verify=True)
117    assert exists
118
119
120def test_nonexistent_lag_does_not_exist(placeboify, maybe_sleep):
121    client = placeboify.client("directconnect")
122    exists = lag_module.lag_exists(client=client,
123                                   lag_id="dxlag-XXXXXXXX",
124                                   lag_name="doesntexist",
125                                   verify=True)
126    assert not exists
127
128
129def test_lag_changed_true(placeboify, maybe_sleep, dependencies):
130    client = placeboify.client("directconnect")
131    status = lag_module.lag_status(client=client, lag_id=dependencies.lag_1.get("lag_id"))
132    assert lag_module.lag_changed(status, "new_name", 1)
133
134
135def test_lag_changed_true_no(placeboify, maybe_sleep, dependencies):
136    client = placeboify.client("directconnect")
137    status = lag_module.lag_status(client=client, lag_id=dependencies.lag_1.get("lag_id"))
138    assert not lag_module.lag_changed(status, "ansible_lag_1", 0)
139
140
141def test_update_lag(placeboify, maybe_sleep, dependencies):
142    client = placeboify.client("directconnect")
143    status_before = lag_module.lag_status(client=client, lag_id=dependencies.lag_2.get("lag_id"))
144    lag_module.update_lag(client,
145                          lag_id=dependencies.lag_2.get("lag_id"),
146                          lag_name="ansible_lag_2_update",
147                          min_links=0,
148                          wait=False,
149                          wait_timeout=0,
150                          num_connections=1)
151    status_after = lag_module.lag_status(client=client, lag_id=dependencies.lag_2.get("lag_id"))
152    assert status_before != status_after
153
154    # remove the lag name from the statuses and verify it was the only thing changed
155    del status_before['lagName']
156    del status_after['lagName']
157    assert status_before == status_after
158
159
160def test_delete_nonexistent_lag(placeboify, maybe_sleep):
161    client = placeboify.client("directconnect")
162    changed = lag_module.ensure_absent(client, "dxlag-XXXXXXXX", "doesntexist", True, True, True, 120)
163    assert not changed
164
165
166def test_delete_lag_with_connections_without_force_delete(placeboify, maybe_sleep, dependencies):
167    client = placeboify.client("directconnect")
168    with pytest.raises(Exception) as error_message:
169        lag_module.ensure_absent(client, dependencies.lag_1.get("lag_id"), "ansible_lag_1", False, True, True, 120)
170        assert "To force deletion of the LAG use delete_force: True" in error_message
171
172
173def test_delete_lag_with_connections(placeboify, maybe_sleep, dependencies):
174    client = placeboify.client("directconnect")
175    changed = lag_module.ensure_absent(client, dependencies.lag_1.get("lag_id"), "ansible_lag_1", True, True, True, 120)
176    assert changed
177