Skip to content

Commit fae6e63

Browse files
authored
Merge branch 'main' into aap-21045
2 parents 3ae523c + c719e7a commit fae6e63

File tree

14 files changed

+210
-8
lines changed

14 files changed

+210
-8
lines changed

src/aap_eda/api/serializers/activation.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ class Meta:
111111
"awx_token_id",
112112
"credentials",
113113
"event_streams",
114+
"log_level",
114115
]
115116
read_only_fields = [
116117
"id",
@@ -161,6 +162,7 @@ class Meta:
161162
"awx_token_id",
162163
"credentials",
163164
"event_streams",
165+
"log_level",
164166
]
165167
read_only_fields = ["id", "created_at", "modified_at"]
166168

@@ -199,6 +201,7 @@ def to_representation(self, activation):
199201
"awx_token_id": activation.awx_token_id,
200202
"credentials": credentials,
201203
"event_streams": event_streams,
204+
"log_level": activation.log_level,
202205
}
203206

204207

@@ -219,6 +222,7 @@ class Meta:
219222
"awx_token_id",
220223
"credentials",
221224
"event_streams",
225+
"log_level",
222226
]
223227

224228
rulebook_id = serializers.IntegerField(
@@ -354,6 +358,7 @@ class Meta:
354358
"awx_token_id",
355359
"credentials",
356360
"event_streams",
361+
"log_level",
357362
]
358363
read_only_fields = ["id", "created_at", "modified_at", "restarted_at"]
359364

@@ -432,6 +437,7 @@ def to_representation(self, activation):
432437
"awx_token_id": activation.awx_token_id,
433438
"credentials": credentials,
434439
"event_streams": event_streams,
440+
"log_level": activation.log_level,
435441
}
436442

437443

src/aap_eda/api/serializers/event_stream.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ class Meta:
125125
"decision_environment_id",
126126
"user",
127127
"credentials",
128+
"log_level",
128129
*read_only_fields,
129130
]
130131

@@ -177,6 +178,7 @@ class Meta:
177178
"user",
178179
"restart_policy",
179180
"credentials",
181+
"log_level",
180182
]
181183

182184
def create(self, validated_data):

src/aap_eda/core/enums.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from enum import Enum
1616

1717

18+
# TODO(alex): migrate to django.db.models.TextChoices
1819
class DjangoStrEnum(str, Enum):
1920
@classmethod
2021
def choices(cls):
@@ -114,3 +115,11 @@ class ProcessParentType(DjangoStrEnum):
114115

115116
ACTIVATION = "activation"
116117
EVENT_STREAM = "event_stream"
118+
119+
120+
class RulebookProcessLogLevel(DjangoStrEnum):
121+
"""Types of log levels for a rulebook process."""
122+
123+
DEBUG = "debug"
124+
INFO = "info"
125+
ERROR = "error"
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Generated by Django 4.2.7 on 2024-02-19 16:38
2+
3+
from django.db import migrations, models
4+
5+
import aap_eda.core.utils
6+
7+
8+
class Migration(migrations.Migration):
9+
dependencies = [
10+
("core", "0025_rename_args_eventstream_source_args"),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name="activation",
16+
name="log_level",
17+
field=models.CharField(
18+
choices=[
19+
("debug", "debug"),
20+
("info", "info"),
21+
("error", "error"),
22+
],
23+
default=aap_eda.core.utils.get_default_log_level,
24+
max_length=20,
25+
),
26+
),
27+
migrations.AddField(
28+
model_name="eventstream",
29+
name="log_level",
30+
field=models.CharField(
31+
choices=[
32+
("debug", "debug"),
33+
("info", "info"),
34+
("error", "error"),
35+
],
36+
default=aap_eda.core.utils.get_default_log_level,
37+
max_length=20,
38+
),
39+
),
40+
]

src/aap_eda/core/models/activation.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414

1515
from django.db import models
1616

17-
from aap_eda.core.enums import ActivationStatus, RestartPolicy
17+
from aap_eda.core.enums import (
18+
ActivationStatus,
19+
RestartPolicy,
20+
RulebookProcessLogLevel,
21+
)
22+
from aap_eda.core.utils import get_default_log_level
1823
from aap_eda.services.activation.engine.common import ContainerableMixin
1924

2025
from .mixins import StatusHandlerModelMixin
@@ -102,3 +107,8 @@ class Meta:
102107
"EventStream",
103108
default=None,
104109
)
110+
log_level = models.CharField(
111+
max_length=20,
112+
choices=RulebookProcessLogLevel.choices(),
113+
default=get_default_log_level,
114+
)

src/aap_eda/core/models/event_stream.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@
1616

1717
from django.db import models
1818

19-
from aap_eda.core.enums import ActivationStatus, RestartPolicy
19+
from aap_eda.core.enums import (
20+
ActivationStatus,
21+
RestartPolicy,
22+
RulebookProcessLogLevel,
23+
)
24+
from aap_eda.core.utils import get_default_log_level
2025
from aap_eda.services.activation.engine.common import ContainerableMixin
2126

2227
from .mixins import StatusHandlerModelMixin
@@ -90,6 +95,11 @@ class EventStream(StatusHandlerModelMixin, ContainerableMixin, models.Model):
9095
credentials = models.ManyToManyField(
9196
"Credential", related_name="event_streams", default=None
9297
)
98+
log_level = models.CharField(
99+
max_length=20,
100+
choices=RulebookProcessLogLevel.choices(),
101+
default=get_default_log_level,
102+
)
93103

94104
class Meta:
95105
db_table = "core_event_stream"

src/aap_eda/core/utils/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,11 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
15+
from django.conf import settings
16+
17+
from aap_eda.core.enums import RulebookProcessLogLevel
18+
19+
20+
def get_default_log_level() -> RulebookProcessLogLevel:
21+
return settings.ANSIBLE_RULEBOOK_LOG_LEVEL

src/aap_eda/services/activation/engine/common.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def get_command_line_parameters(self) -> dict[str, tp.Any]:
155155
return {
156156
"id": str(self.latest_instance.id),
157157
"ws_url": self._get_ws_url(),
158-
"log_level": settings.ANSIBLE_RULEBOOK_LOG_LEVEL,
158+
"log_level": self._get_log_level(),
159159
"ws_ssl_verify": settings.WEBSOCKET_SSL_VERIFY,
160160
"ws_token_url": self._get_ws_token_url(),
161161
"ws_access_token": access_token,
@@ -229,6 +229,15 @@ def _build_cmdline(self) -> AnsibleRulebookCmdLine:
229229
skip_audit_events=params["skip_audit_events"],
230230
)
231231

232+
def _get_log_level(self) -> tp.Optional[str]:
233+
"""Return the log level to use by ansible-rulebook."""
234+
level_map = {
235+
"debug": "-vv",
236+
"info": "-v",
237+
"error": None,
238+
}
239+
return level_map[self.log_level]
240+
232241
def _get_container_name(self) -> str:
233242
"""Return the name to use for the ContainerRequest."""
234243
return (

src/aap_eda/settings/default.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@
7676
from django.core.exceptions import ImproperlyConfigured
7777
from split_settings.tools import include
7878

79+
from aap_eda.core.enums import RulebookProcessLogLevel
80+
7981
default_settings_file = "/etc/eda/settings.yaml"
8082

8183
settings = dynaconf.Dynaconf(
@@ -450,7 +452,29 @@ def _get_secret_key() -> str:
450452
# ---------------------------------------------------------
451453
# RULEBOOK ENGINE LOG LEVEL
452454
# ---------------------------------------------------------
453-
ANSIBLE_RULEBOOK_LOG_LEVEL = settings.get("ANSIBLE_RULEBOOK_LOG_LEVEL", "-v")
455+
456+
457+
# For backwards compatibility, from the old value "-v" to the new value "info"
458+
def get_rulebook_process_log_level() -> RulebookProcessLogLevel:
459+
log_level = settings.get(
460+
"ANSIBLE_RULEBOOK_LOG_LEVEL",
461+
"error",
462+
)
463+
if log_level is None:
464+
return RulebookProcessLogLevel.ERROR
465+
if log_level.lower() == "-v":
466+
return RulebookProcessLogLevel.INFO
467+
if log_level.lower() == "-vv":
468+
return RulebookProcessLogLevel.DEBUG
469+
if log_level not in RulebookProcessLogLevel.values():
470+
raise ImproperlyConfigured(
471+
f"Invalid log level '{log_level}' for ANSIBLE_RULEBOOK_LOG_LEVEL"
472+
f" setting. Valid values are: {RulebookProcessLogLevel.values()}"
473+
)
474+
return RulebookProcessLogLevel(log_level)
475+
476+
477+
ANSIBLE_RULEBOOK_LOG_LEVEL = get_rulebook_process_log_level()
454478
ANSIBLE_RULEBOOK_FLUSH_AFTER = settings.get("ANSIBLE_RULEBOOK_FLUSH_AFTER", 1)
455479

456480
# Experimental LDAP Integration https://issues.redhat.com/browse/AAP-16938

tests/integration/api/test_activation.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"restart_policy": RestartPolicy.ON_FAILURE,
4444
"restart_count": 0,
4545
"status_message": "",
46+
"log_level": "debug",
4647
}
4748

4849
TEST_AWX_TOKEN = {
@@ -220,6 +221,7 @@ def create_activation(fks: dict):
220221
activation_data["rulebook_id"] = fks["rulebook_id"]
221222
activation_data["extra_var_id"] = fks["extra_var_id"]
222223
activation_data["user_id"] = fks["user_id"]
224+
activation_data["log_level"] = "debug"
223225
activation = models.Activation(**activation_data)
224226
activation.save()
225227

@@ -268,6 +270,7 @@ def test_create_activation(client: APIClient):
268270
data,
269271
activation,
270272
)
273+
assert data["log_level"] == "debug"
271274
if activation.project:
272275
assert data["project"] == {"id": activation.project.id, **TEST_PROJECT}
273276
else:

tests/integration/services/activation/test_activation.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def activation(activation_no_instance) -> models.Activation:
5656
def test_command_line_parameters(activation):
5757
params = activation.get_command_line_parameters()
5858
assert params["ws_url"] is not None
59-
assert params["log_level"] is not None
59+
assert params["log_level"] is None
6060
assert params["ws_ssl_verify"] is not None
6161
assert params["ws_token_url"] is not None
6262
assert params["ws_access_token"] is not None
@@ -101,3 +101,19 @@ def test_get_container_request_no_instance(activation_no_instance):
101101
"""Test the construction of a ContainerRequest."""
102102
with pytest.raises(ContainerableInvalidError):
103103
activation_no_instance.get_container_request()
104+
105+
106+
@pytest.mark.parametrize(
107+
"value,expected",
108+
[
109+
("debug", "-vv"),
110+
("info", "-v"),
111+
("error", None),
112+
],
113+
)
114+
@pytest.mark.django_db
115+
def test_log_level_param_activation(activation, value, expected):
116+
activation.log_level = value
117+
activation.save(update_fields=["log_level"])
118+
request = activation.get_container_request()
119+
assert request.cmdline.log_level == expected

tests/integration/services/activation/test_event_stream.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def event_stream(event_stream_no_instance) -> models.EventStream:
5656
def test_command_line_parameters(event_stream):
5757
params = event_stream.get_command_line_parameters()
5858
assert params["ws_url"] is not None
59-
assert params["log_level"] is not None
59+
assert params["log_level"] is None
6060
assert params["ws_ssl_verify"] is not None
6161
assert params["ws_token_url"] is not None
6262
assert params["ws_access_token"] is not None
@@ -101,3 +101,19 @@ def test_get_container_request_no_instance(event_stream_no_instance):
101101
"""Test the construction of a ContainerRequest."""
102102
with pytest.raises(ContainerableInvalidError):
103103
event_stream_no_instance.get_container_request()
104+
105+
106+
@pytest.mark.parametrize(
107+
"value,expected",
108+
[
109+
("debug", "-vv"),
110+
("info", "-v"),
111+
("error", None),
112+
],
113+
)
114+
@pytest.mark.django_db
115+
def test_log_level_param_event_stream(event_stream, value, expected):
116+
event_stream.log_level = value
117+
event_stream.save(update_fields=["log_level"])
118+
request = event_stream.get_container_request()
119+
assert request.cmdline.log_level == expected

tests/integration/services/activation/test_manager.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ def basic_activation(
108108
rulebook=default_rulebook,
109109
# rulebook_rulesets is populated by the serializer
110110
rulebook_rulesets=default_rulebook.rulesets,
111+
log_level="info",
111112
)
112113

113114

@@ -146,7 +147,6 @@ def test_get_container_request(
146147
"""Test build_cmdline."""
147148
override_settings = {
148149
"WEBSOCKET_BASE_URL": "ws://localhost:8000",
149-
"ANSIBLE_RULEBOOK_LOG_LEVEL": "-vv",
150150
"WEBSOCKET_SSL_VERIFY": "no",
151151
"RULEBOOK_LIVENESS_CHECK_SECONDS": 73,
152152
}
@@ -156,7 +156,7 @@ def test_get_container_request(
156156
assert isinstance(request, ContainerRequest)
157157
cmdline = request.cmdline
158158
assert cmdline.ws_url.startswith(override_settings["WEBSOCKET_BASE_URL"])
159-
assert cmdline.log_level == override_settings["ANSIBLE_RULEBOOK_LOG_LEVEL"]
159+
assert cmdline.log_level == "-v"
160160
assert cmdline.ws_ssl_verify == override_settings["WEBSOCKET_SSL_VERIFY"]
161161
assert (
162162
cmdline.heartbeat

0 commit comments

Comments
 (0)