Merge ~renanrodrigo/ubuntu/+source/ubuntu-advantage-tools:upload-27.11.3-kinetic into ubuntu/+source/ubuntu-advantage-tools:ubuntu/devel

Proposed by Renan Rodrigo
Status: Needs review
Proposed branch: ~renanrodrigo/ubuntu/+source/ubuntu-advantage-tools:upload-27.11.3-kinetic
Merge into: ubuntu/+source/ubuntu-advantage-tools:ubuntu/devel
Diff against target: 657 lines (+198/-69)
23 files modified
apt-hook/json-hook.cc (+13/-5)
debian/changelog (+12/-0)
debian/ubuntu-advantage-tools.postinst (+23/-0)
features/api_full_auto_attach.feature (+1/-1)
features/apt_messages.feature (+11/-2)
features/cloud_pro_clone.feature (+0/-1)
features/daemon.feature (+3/-2)
features/docker.feature (+3/-1)
features/environment.py (+4/-4)
features/ubuntu_pro.feature (+3/-0)
integration-requirements.txt (+1/-1)
uaclient/actions.py (+24/-16)
uaclient/cli.py (+9/-0)
uaclient/config.py (+12/-0)
uaclient/jobs/update_messaging.py (+21/-27)
uaclient/messages.py (+0/-4)
uaclient/system.py (+13/-0)
uaclient/tests/test_actions.py (+36/-1)
uaclient/tests/test_cli_config_set.py (+2/-1)
uaclient/tests/test_cli_config_show.py (+1/-0)
uaclient/tests/test_cli_config_unset.py (+1/-1)
uaclient/tests/test_config.py (+4/-1)
uaclient/version.py (+1/-1)
Reviewer Review Type Date Requested Status
Paride Legovini (community) Approve
Robie Basak ubuntu-sru Approve
Review via email: mp+431300@code.launchpad.net

Description of the change

This is the 27.11.3 release of ubuntu-advantage-tools.
This brings a couple hotfixes to bugs opened right after 27.11.2 was released.
Please refer to the changelog to see what has changed

To post a comment you must log in.
Revision history for this message
Robie Basak (racb) wrote :

A couple of comments. This isn't a full review.

1) Let's be honest. Moving the message to the end, and/or providing a command to change configuration to opt-out, is certainly not fixing the spirit of bug 1992026 as it was filed, and it's distasteful to pretend that it is. I doubt that those who marked themselves as affected would consider that bug resolved or even mitigated by these changes. By all means go ahead and make these changes if you think they provide mitigation, but the correct status of bug 1992026 should then be "Won't Fix" or "Opinion", perhaps with a comment explaining what mitigating steps you are taking instead. "Fix Released" however would be wrong. Feel free to use different bugs to track what you _are_ changing, for SRU purposes, etc.

2) That "-q/-qq" doesn't suppress the message certainly seems like a bug to me. If you can't fix it directly in your hook because apt doesn't expose that information to you, then maybe it needs fixing by first changing the hook interface in apt. I suggest you file a separate bug to track that with both apt and ubuntu-advantage-tools tasks. It isn't reasonable to say that it can't be fixed in ubuntu-advantage-tools unless there's at least an open bug against apt.

Revision history for this message
Renan Rodrigo (renanrodrigo) wrote :

Thanks for the comments @racb.

1) We decided that product people will be responsible for updating that bug, either commenting or changing status will be up to them. We removed the (#) from the changelog entry referencing the bug, so we keep the pointer but automation does not consider it fixed.

2) https://bugs.launchpad.net/ubuntu/+source/apt/+bug/1992472 filed against APT. I doubt they will fix and release this to all LTS before our message goes away anyway, so I am not linking ourselves there. We can leverage the functionality in the future if any other message comes up.

Revision history for this message
Robie Basak (racb) wrote :

> We removed the (#) from the changelog entry referencing the bug, so we keep the pointer but automation does not consider it fixed.

OK, but you do need a bug to track the regular SRU verification of the new release, please, and it won't be able to be this 1992026 bug then. Since we allow major version updates for this package, and you have test coverage for the changes you're making, this doesn't need anything more than your usual test plan, but we need a bug to track the status of that QA process.

Alternatively, you can do this SRU without relying on your exception and have a separate bug to track every change and verify each one, but I assume that's more tedious and so you'll want to do it the former way.

Revision history for this message
Grant Orndorff (orndorffgrant) wrote :

Thanks racb!

renanrodrigo will be out for a while so I'll take this over in the morning. I'll create a bug to track the QA like we usually do and reference that in the changelog.

There also may be some minor tweaks pending a discussion early tomorrow.

Not sure if I can update this MP since it's owned by renanrodrigo or if I'll need to create a new one.

Regardless, I'll ping you again as soon as this is ready.

Revision history for this message
Robie Basak (racb) wrote :

SRU +1 on commit 9417e483c9eb15e012bf73c1ae1beffb4903886f

Your implementation of "pro config set apt_news=False" seems fine. However, I suggest that users who want to disable that also want to disable everything else this package does in relation to the apt hook, so removing /etc/apt/apt.conf.d/20apt-esm-hook.conf would be my recommendation to those users instead. This is a configuration change in /etc so must be preserved by packaging policy.

review: Approve (ubuntu-sru)
Revision history for this message
Robie Basak (racb) wrote :

> SRU +1 on commit 9417e483c9eb15e012bf73c1ae1beffb4903886f

(but with bug reference changes as discussed)

Revision history for this message
Paride Legovini (paride) wrote :

I am also +1 on the technical aspects of this MP. Robie's comments on the non strictly technical aspects are way more insightful than what I could have come up with, I agree with them and I'm happy with the middle ground you found, given that there is no perfect fix to the concerns that were raised. I can proceed sponsoring once the bug references are updated, just ping me.

As a general comment on this MP: I think this could have been uploaded as initially proposed. The discussion here did improve the upload and allow for better bug tracking and management, but bug statuses can be adjusted after uploading, and same for filing extra bugs. This is all basically invisible to the end user. In case it isn't clear: I'm writing this with your PPU application in mind :-)

review: Approve
Revision history for this message
Grant Orndorff (orndorffgrant) wrote :

Thank you racb and paride for the reviews!

As mentioned in my last comment there are some tweaks incoming. You can see a preview of what they might be here: https://github.com/canonical/ubuntu-advantage-client/pull/2293

They will at least include:
* modifying this output to only appear when using `apt` (and not `apt-get`)
* fixing https://github.com/canonical/ubuntu-advantage-client/issues/2294
* a change to the message itself, still not finalized

I've been told the message will be finalized by tomorrow, so hopefully by tomorrow I will have everything in place (SRU bug, updated MP) for another round of review and we can get this out by early next week.

I'll be sure to ping you both when it is ready.

Unmerged commits

9417e48... by Renan Rodrigo

chore: fix the changelog entry for 27.11.3

Signed-off-by: Renan Rodrigo <email address hidden>

520d708... by Renan Rodrigo

new release 27.11.3

Signed-off-by: Renan Rodrigo <email address hidden>

e15a247... by Lucas Albuquerque Medeiros de Moura

collect-logs: Do not fail if we can't read a file

Currently, if we fail to read a file, we will error out
during the execution of the command. We are updating that
so that we will just warn the user that a file could not be read
and proceed with the command.

LP: #1991858

6e4c406... by Renan Rodrigo

tests: add check for APT messages disabling apt_news

Signed-off-by: Renan Rodrigo <email address hidden>

41f5a7a... by Grant Orndorff

messaging: move pro beta message and add config option to disable it

The placement of the "Try Ubuntu Pro beta..." message in apt output is
considered distasteful. To make it somewhat more sensible, we're moving
the message to the bottom of apt output, so that it is more clearly a
separate banner from the normal output.

We're also adding a config option to disable this post-apt-output
banner: pro config set apt_news=false

LP: #1992026

74f2f55... by Renan Rodrigo

tests: fix 'or' condition in docker feature

Signed-off-by: Renan Rodrigo <email address hidden>

e663f76... by Grant Orndorff

tests: various fixups to bring tests inline with expectations

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/apt-hook/json-hook.cc b/apt-hook/json-hook.cc
2index 0efaa81..bacf033 100644
3--- a/apt-hook/json-hook.cc
4+++ b/apt-hook/json-hook.cc
5@@ -257,23 +257,31 @@ int run()
6
7 json_object_put(hello_req.root_msg);
8
9- jsonrpc_request stats_req;
10- success = read_jsonrpc_request(socket_in, stats_req);
11+ jsonrpc_request hook_req;
12+ success = read_jsonrpc_request(socket_in, hook_req);
13 if (!success) {
14 std::cerr << "ua-hook: failed to read hook msg" << std::endl;
15 return 0;
16 }
17- if (stats_req.method == "org.debian.apt.hooks.install.statistics") {
18+ if (hook_req.method == "org.debian.apt.hooks.install.statistics") {
19 security_package_counts counts;
20- success = count_security_packages_from_apt_stats_json(stats_req.params, counts);
21+ success = count_security_packages_from_apt_stats_json(hook_req.params, counts);
22 if (success) {
23 std::string message = create_count_message(counts);
24 if (message != "") {
25 std::cout << message << std::endl;
26 }
27 }
28+ } else if (hook_req.method == "org.debian.apt.hooks.install.post") {
29+ std::ifstream apt_news_flag_file("/var/lib/ubuntu-advantage/flags/show-apt-news");
30+ if (apt_news_flag_file.is_open()) {
31+ std::cout << std::endl;
32+ std::cout << "Try Ubuntu Pro beta with a free personal subscription on up to 5 machines." << std::endl;
33+ std::cout << "Learn more at https://ubuntu.com/pro" << std::endl;
34+ apt_news_flag_file.close();
35+ }
36 }
37- json_object_put(stats_req.root_msg);
38+ json_object_put(hook_req.root_msg);
39
40 jsonrpc_request bye_req;
41 success = read_jsonrpc_request(socket_in, bye_req);
42diff --git a/debian/changelog b/debian/changelog
43index a5acfc4..f6dbb14 100644
44--- a/debian/changelog
45+++ b/debian/changelog
46@@ -1,3 +1,15 @@
47+ubuntu-advantage-tools (27.11.3~22.10.1) kinetic; urgency=medium
48+
49+ * New upstream release 27.11.3:
50+ - d/postinst: remove the old Ubuntu Pro message and set up the
51+ configurable flag instead
52+ - apport-hook: do not fail if a file cannot be read (LP: #1991858)
53+ - config: add a flag to remove the APT related news (LP: 1992026)
54+ (GH: #2288)
55+ - messaging: move the Ubuntu Pro beta message to the end of the APT output
56+
57+ -- Renan Rodrigo <renanrodrigo@canonical.com> Mon, 10 Oct 2022 15:08:51 -0300
58+
59 ubuntu-advantage-tools (27.11.2~22.10.1) kinetic; urgency=medium
60
61 * New upstream release 27.11.2: (LP: #1991173)
62diff --git a/debian/ubuntu-advantage-tools.postinst b/debian/ubuntu-advantage-tools.postinst
63index 4a677fc..aa2a1a3 100644
64--- a/debian/ubuntu-advantage-tools.postinst
65+++ b/debian/ubuntu-advantage-tools.postinst
66@@ -57,6 +57,11 @@ OLD_LICENSE_CHECK_MARKER_FILE="/var/lib/ubuntu-advantage/marker-license-check"
67 MACHINE_TOKEN_FILE="/var/lib/ubuntu-advantage/private/machine-token.json"
68 PUBLIC_MACHINE_TOKEN_FILE="/var/lib/ubuntu-advantage/machine-token.json"
69
70+UA_MESSAGES_DIR="/var/lib/ubuntu-advantage/messages"
71+APT_ESM_MESSAGE_FILE="$UA_MESSAGES_DIR/apt-pre-invoke-esm-service-status"
72+ESM_APPS_APT_MSG_FILES="$UA_MESSAGES_DIR/apt-pre-invoke-no-packages-apps.tmpl $UA_MESSAGES_DIR/apt-pre-invoke-no-packages-apps $UA_MESSAGES_DIR/apt-pre-invoke-packages-apps.tmpl $UA_MESSAGES_DIR/apt-pre-invoke-packages-apps"
73+UA_FLAGS_DIR="/var/lib/ubuntu-advantage/flags"
74+APT_NEWS_FLAG_FILE="$UA_FLAGS_DIR/show-apt-news"
75
76 # Rename apt config files for ua services removing ubuntu release names
77 redact_ubuntu_release_from_ua_apt_filenames() {
78@@ -384,6 +389,23 @@ machine_token_file.write(content=content)
79 "
80 }
81
82+migrate_ubuntu_pro_beta_banner() {
83+ PREVIOUS_PKG_VER=$1
84+ # This only shipped in 27.11.2~
85+ if dpkg --compare-versions "$PREVIOUS_PKG_VER" ge "27.11.2~" \
86+ && dpkg --compare-versions "$PREVIOUS_PKG_VER" lt "27.11.3~"; then
87+ # if the banner was present, remove it and add the new flag file which is configurable
88+ if [ -f $APT_ESM_MESSAGE_FILE ]; then
89+ if cat $APT_ESM_MESSAGE_FILE | grep -q "Try Ubuntu Pro beta"; then
90+ rm -f $APT_ESM_MESSAGE_FILE
91+ rm -f $ESM_APPS_APT_MSG_FILES
92+ mkdir -p $UA_FLAGS_DIR
93+ touch $APT_NEWS_FLAG_FILE
94+ fi
95+ fi
96+ fi
97+}
98+
99 case "$1" in
100 configure)
101 PREVIOUS_PKG_VER=$2
102@@ -462,6 +484,7 @@ case "$1" in
103 if [ -f $MACHINE_TOKEN_FILE ] && [ ! -f $PUBLIC_MACHINE_TOKEN_FILE ]; then
104 create_public_machine_token_file
105 fi
106+ migrate_ubuntu_pro_beta_banner $PREVIOUS_PKG_VER
107 ;;
108 esac
109
110diff --git a/features/api_full_auto_attach.feature b/features/api_full_auto_attach.feature
111index 240e06f..c65fca5 100644
112--- a/features/api_full_auto_attach.feature
113+++ b/features/api_full_auto_attach.feature
114@@ -27,7 +27,7 @@ Feature: Full Auto-Attach Endpoint
115 """
116 Then stdout matches regexp:
117 """
118- livepatch +yes +disabled +Canonical Livepatch service
119+ livepatch +yes +(disabled|n/a) +Canonical Livepatch service
120 """
121 Examples:
122 | release |
123diff --git a/features/apt_messages.feature b/features/apt_messages.feature
124index 27d67cb..eee585d 100644
125--- a/features/apt_messages.feature
126+++ b/features/apt_messages.feature
127@@ -225,9 +225,10 @@ Feature: APT Messages
128 Building dependency tree...
129 Reading state information...
130 Calculating upgrade...
131+ 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
132+
133 Try Ubuntu Pro beta with a free personal subscription on up to 5 machines.
134 Learn more at https://ubuntu.com/pro
135- 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
136 """
137 When I attach `contract_token` with sudo
138 When I run `apt-get upgrade --dry-run` with sudo
139@@ -267,9 +268,17 @@ Feature: APT Messages
140 Building dependency tree...
141 Reading state information...
142 Calculating upgrade...
143+ 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded\.
144+
145+ Try Ubuntu Pro beta with a free personal subscription on up to 5 machines.
146+ Learn more at https:\/\/ubuntu.com\/pro
147+ """
148+ When I run `pro config set apt_news=False` with sudo
149+ And I run `apt-get upgrade` with sudo
150+ Then stdout does not match regexp:
151+ """
152 Try Ubuntu Pro beta with a free personal subscription on up to 5 machines.
153 Learn more at https:\/\/ubuntu.com\/pro
154- 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded\.
155 """
156 Examples: ubuntu release
157 | release |
158diff --git a/features/cloud_pro_clone.feature b/features/cloud_pro_clone.feature
159index f08bff0..48aa17a 100644
160--- a/features/cloud_pro_clone.feature
161+++ b/features/cloud_pro_clone.feature
162@@ -2,7 +2,6 @@ Feature: Creating golden images based on Cloud Ubuntu Pro instances
163
164 @series.lts
165 @uses.config.machine_type.aws.pro
166- @uses.config.machine_type.azure.pro
167 @uses.config.machine_type.gcp.pro
168 Scenario Outline: Create a Pro fips-updates image and launch
169 Given a `<release>` machine with ubuntu-advantage-tools installed
170diff --git a/features/daemon.feature b/features/daemon.feature
171index 593c86d..0b33c37 100644
172--- a/features/daemon.feature
173+++ b/features/daemon.feature
174@@ -104,9 +104,10 @@ Feature: Pro Upgrade Daemon only runs in environments where necessary
175 """
176 Active: active \(running\)
177 """
178- Then on `xenial`, systemd status output says memory usage is less than `14` MB
179+ # TODO find out what caused memory to go up, try to lower it again
180+ Then on `xenial`, systemd status output says memory usage is less than `15` MB
181 Then on `bionic`, systemd status output says memory usage is less than `13` MB
182- Then on `focal`, systemd status output says memory usage is less than `11` MB
183+ Then on `focal`, systemd status output says memory usage is less than `12` MB
184 Then on `jammy`, systemd status output says memory usage is less than `12` MB
185
186 When I run `cat /var/log/ubuntu-advantage-daemon.log` with sudo
187diff --git a/features/docker.feature b/features/docker.feature
188index e4ac590..2e82266 100644
189--- a/features/docker.feature
190+++ b/features/docker.feature
191@@ -19,7 +19,9 @@ Feature: Build docker images with pro services
192 apt-get update \
193 && apt-get install --no-install-recommends -y ubuntu-advantage-tools ca-certificates \
194
195- && dpkg -i /ua.deb \
196+ && ((dpkg -i /ua.deb || true)) \
197+
198+ && apt-get install -f \
199
200 && pro attach --attach-config /run/secrets/ua-attach-config \
201
202diff --git a/features/environment.py b/features/environment.py
203index 39013d0..bfe0042 100644
204--- a/features/environment.py
205+++ b/features/environment.py
206@@ -23,10 +23,6 @@ DEFAULT_UA_PPA_KEYID = "6E34E7116C0BC933"
207
208 USERDATA_BLOCK_AUTO_ATTACH_IMG = """\
209 #cloud-config
210-[bootcmd, once]:
211- - cp /usr/bin/ua /usr/bin/ua.orig
212- - 'echo "#!/bin/sh\ndate >> /root/ua-calls\n" > /usr/bin/ua'
213- - chmod 755 /usr/bin/ua
214 """
215
216 # we can't use write_files because it will clash with the
217@@ -40,8 +36,10 @@ runcmd:
218 USERDATA_RUNCMD_ENABLE_PROPOSED = """
219 runcmd:
220 - printf \"deb http://archive.ubuntu.com/ubuntu/ {series}-proposed main\" > /etc/apt/sources.list.d/uaclient-proposed.list
221+ - printf \"deb http://archive.ubuntu.com/ubuntu/ {series}-proposed universe\" > /etc/apt/sources.list.d/uaclient-proposed-universe.list
222 - "printf \\"Package: *\\nPin: release a={series}-proposed\\nPin-Priority: 400\\n\\" > /etc/apt/preferences.d/lower-proposed"
223 - "printf \\"Package: ubuntu-advantage-tools\\nPin: release a={series}-proposed\\nPin-Priority: 1001\\n\\" > /etc/apt/preferences.d/uaclient-proposed"
224+ - "printf \\"Package: ubuntu-advantage-pro\\nPin: release a={series}-proposed\\nPin-Priority: 1001\\n\\" > /etc/apt/preferences.d/uaclientpro-proposed"
225 """ # noqa: E501
226
227 USERDATA_APT_SOURCE_PPA = """\
228@@ -333,6 +331,8 @@ class UAClientBehaveConfig:
229 def before_all(context: Context) -> None:
230 """behave will invoke this before anything else happens."""
231 context.config.setup_logging()
232+ logging.getLogger("botocore").setLevel(logging.INFO)
233+ logging.getLogger("boto3").setLevel(logging.INFO)
234 userdata = context.config.userdata
235 if userdata:
236 logging.debug("Userdata key / value pairs:")
237diff --git a/features/ubuntu_pro.feature b/features/ubuntu_pro.feature
238index f23dcde..c373a95 100644
239--- a/features/ubuntu_pro.feature
240+++ b/features/ubuntu_pro.feature
241@@ -23,6 +23,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image
242 """
243 And I verify `/var/log/squid/access.log` is empty on `proxy` machine
244 When I run `pro auto-attach` with sudo
245+ When I run `pro status --all` with sudo
246 Then stdout matches regexp:
247 """
248 SERVICE +ENTITLED STATUS DESCRIPTION
249@@ -94,6 +95,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image
250 """
251 And I verify `/var/log/squid/access.log` is empty on `proxy` machine
252 When I run `pro auto-attach` with sudo
253+ When I run `pro status --all` with sudo
254 Then stdout matches regexp:
255 """
256 SERVICE +ENTITLED STATUS DESCRIPTION
257@@ -165,6 +167,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image
258 """
259 And I verify `/var/log/squid/access.log` is empty on `proxy` machine
260 When I run `pro auto-attach` with sudo
261+ When I run `pro status --all` with sudo
262 Then stdout matches regexp:
263 """
264 SERVICE +ENTITLED STATUS DESCRIPTION
265diff --git a/integration-requirements.txt b/integration-requirements.txt
266index 9eaf14f..de2698d 100644
267--- a/integration-requirements.txt
268+++ b/integration-requirements.txt
269@@ -2,7 +2,7 @@
270 behave
271 jsonschema
272 PyHamcrest
273-pycloudlib @ git+https://github.com/canonical/pycloudlib.git@25cca01b24d111e00e91a86eb1021b88592e069e
274+pycloudlib @ git+https://github.com/canonical/pycloudlib.git@e7c4a42eb98a914b084b253c3f96c960de42e8fa
275 toml==0.10
276
277
278diff --git a/uaclient/actions.py b/uaclient/actions.py
279index 9b1af00..3f602e8 100644
280--- a/uaclient/actions.py
281+++ b/uaclient/actions.py
282@@ -160,6 +160,23 @@ def _write_command_output_to_file(
283 system.write_file(filename, out)
284
285
286+def _get_state_files(cfg: config.UAConfig):
287+ # include cfg log files here because they could be set to non default
288+ return [
289+ cfg.cfg_path or DEFAULT_CONFIG_FILE,
290+ cfg.log_file,
291+ cfg.timer_log_file,
292+ cfg.daemon_log_file,
293+ cfg.data_path("jobs-status"),
294+ CLOUD_BUILD_INFO,
295+ *(
296+ entitlement.repo_list_file_tmpl.format(name=entitlement.name)
297+ for entitlement in entitlements.ENTITLEMENT_CLASSES
298+ if issubclass(entitlement, entitlements.repo.RepoEntitlement)
299+ ),
300+ ]
301+
302+
303 def collect_logs(cfg: config.UAConfig, output_dir: str):
304 """
305 Write all relevant Ubuntu Pro logs to the specified directory
306@@ -199,28 +216,19 @@ def collect_logs(cfg: config.UAConfig, output_dir: str):
307 return_codes=[0, 3],
308 )
309
310- # include cfg log files here because they could be set to non default
311- state_files = [
312- cfg.cfg_path or DEFAULT_CONFIG_FILE,
313- cfg.log_file,
314- cfg.timer_log_file,
315- cfg.daemon_log_file,
316- cfg.data_path("jobs-status"),
317- CLOUD_BUILD_INFO,
318- *(
319- entitlement.repo_list_file_tmpl.format(name=entitlement.name)
320- for entitlement in entitlements.ENTITLEMENT_CLASSES
321- if issubclass(entitlement, entitlements.repo.RepoEntitlement)
322- ),
323- ]
324+ state_files = _get_state_files(cfg)
325
326 # also get default logrotated log files
327 for f in state_files + glob.glob(DEFAULT_LOG_PREFIX + "*"):
328 if os.path.isfile(f):
329 try:
330 content = system.load_file(f)
331- except PermissionError as e:
332- logging.warning(e)
333+ except Exception as e:
334+ # If we fail to load that file for any reason we will
335+ # not break the command, we will instead warn the user
336+ # about the issue and try to process the other files
337+ logging.warning("Failed to load file: %s\n%s", f, str(e))
338+ continue
339 content = util.redact_sensitive_logs(content)
340 if os.getuid() == 0:
341 # if root, overwrite the original with redacted content
342diff --git a/uaclient/cli.py b/uaclient/cli.py
343index 3473414..55f8bec 100644
344--- a/uaclient/cli.py
345+++ b/uaclient/cli.py
346@@ -49,7 +49,9 @@ from uaclient.entitlements.entitlement_status import (
347 CanEnableFailureReason,
348 )
349 from uaclient.jobs.update_messaging import (
350+ clear_apt_news_flag,
351 refresh_motd,
352+ set_apt_news_flag,
353 update_apt_and_motd_messages,
354 )
355
356@@ -1022,6 +1024,13 @@ def action_config_set(args, *, cfg, **kwargs):
357 "<value> for interval must be a positive integer."
358 ).format(set_key, set_value)
359 )
360+ elif set_key == "apt_news":
361+ set_value = set_value.lower() == "true"
362+ if set_value:
363+ set_apt_news_flag(cfg)
364+ else:
365+ clear_apt_news_flag(cfg)
366+
367 setattr(cfg, set_key, set_value)
368
369
370diff --git a/uaclient/config.py b/uaclient/config.py
371index 2b43d55..bb7bb06 100644
372--- a/uaclient/config.py
373+++ b/uaclient/config.py
374@@ -49,6 +49,7 @@ UA_CONFIGURABLE_KEYS = (
375 "update_messaging_timer",
376 "update_status_timer",
377 "metering_timer",
378+ "apt_news",
379 )
380
381 # Basic schema validation top-level keys for parse_config handling
382@@ -304,6 +305,17 @@ class UAConfig:
383 self.cfg["ua_config"]["polling_error_retry_delay"] = value
384 self.write_cfg()
385
386+ @property
387+ def apt_news(self) -> bool:
388+ return self.cfg.get("ua_config", {}).get("apt_news", True)
389+
390+ @apt_news.setter
391+ def apt_news(self, value: bool):
392+ if "ua_config" not in self.cfg:
393+ self.cfg["ua_config"] = {}
394+ self.cfg["ua_config"]["apt_news"] = value
395+ self.write_cfg()
396+
397 def check_lock_info(self) -> Tuple[int, str]:
398 """Return lock info if config lock file is present the lock is active.
399
400diff --git a/uaclient/jobs/update_messaging.py b/uaclient/jobs/update_messaging.py
401index 4a3893f..8d24cf0 100644
402--- a/uaclient/jobs/update_messaging.py
403+++ b/uaclient/jobs/update_messaging.py
404@@ -28,7 +28,6 @@ from uaclient.messages import (
405 CONTRACT_EXPIRED_MOTD_SOON_TMPL,
406 DISABLED_APT_NO_PKGS_TMPL,
407 DISABLED_APT_PKGS_TMPL,
408- TRY_UBUNTU_PRO_BETA,
409 )
410
411 XENIAL_ESM_URL = "https://ubuntu.com/16-04"
412@@ -68,6 +67,21 @@ UPDATE_NOTIFIER_MOTD_SCRIPT = (
413 )
414
415
416+def set_apt_news_flag(cfg: config.UAConfig):
417+ if (
418+ system.is_current_series_lts()
419+ and not system.is_current_series_active_esm()
420+ and not cfg.is_attached
421+ ):
422+ system.create_file(
423+ os.path.join(cfg.data_dir, "flags", "show-apt-news")
424+ )
425+
426+
427+def clear_apt_news_flag(cfg: config.UAConfig):
428+ system.remove_file(os.path.join(cfg.data_dir, "flags", "show-apt-news"))
429+
430+
431 def get_contract_expiry_status(
432 cfg: config.UAConfig,
433 ) -> Tuple[ContractExpiryStatus, int]:
434@@ -311,32 +325,6 @@ def write_apt_and_motd_templates(cfg: config.UAConfig, series: str) -> None:
435 ],
436 )
437
438- if (
439- system.is_current_series_lts()
440- and not system.is_active_esm(series)
441- and not cfg.is_attached
442- ):
443- _write_template_or_remove(
444- TRY_UBUNTU_PRO_BETA, os.path.join(msg_dir, apps_no_pkg_file)
445- )
446- _write_template_or_remove(
447- TRY_UBUNTU_PRO_BETA, os.path.join(msg_dir, apps_pkg_file)
448- )
449- _write_template_or_remove("", os.path.join(msg_dir, infra_no_pkg_file))
450- _write_template_or_remove("", os.path.join(msg_dir, infra_pkg_file))
451- _write_template_or_remove(
452- "", os.path.join(msg_dir, motd_apps_no_pkg_file)
453- )
454- _write_template_or_remove(
455- "", os.path.join(msg_dir, motd_apps_pkg_file)
456- )
457- _write_template_or_remove(
458- "", os.path.join(msg_dir, motd_infra_no_pkg_file)
459- )
460- _write_template_or_remove(
461- "", os.path.join(msg_dir, motd_infra_pkg_file)
462- )
463-
464
465 def write_esm_announcement_message(cfg: config.UAConfig, series: str) -> None:
466 """Write human-readable messages if ESM is offered on this LTS release.
467@@ -396,6 +384,12 @@ def update_apt_and_motd_messages(cfg: config.UAConfig) -> bool:
468
469 # Announce ESM availabilty on active ESM LTS releases
470 # write_esm_announcement_message(cfg, series)
471+
472+ if cfg.apt_news:
473+ set_apt_news_flag(cfg)
474+ else:
475+ clear_apt_news_flag(cfg)
476+
477 write_apt_and_motd_templates(cfg, series)
478 # Now that we've setup/cleanedup templates render them with apt-hook
479 system.subp(
480diff --git a/uaclient/messages.py b/uaclient/messages.py
481index 95f1605..e3061be 100644
482--- a/uaclient/messages.py
483+++ b/uaclient/messages.py
484@@ -1034,7 +1034,3 @@ Package names in {bold}bold{end_bold} currently have an available update
485 with '{{service}}' enabled""".format(
486 bold=TxtColor.BOLD, end_bold=TxtColor.ENDC
487 )
488-
489-TRY_UBUNTU_PRO_BETA = """\
490-Try Ubuntu Pro beta with a free personal subscription on up to 5 machines.
491-Learn more at https://ubuntu.com/pro"""
492diff --git a/uaclient/system.py b/uaclient/system.py
493index ef48d0c..3983e84 100644
494--- a/uaclient/system.py
495+++ b/uaclient/system.py
496@@ -1,6 +1,7 @@
497 import datetime
498 import logging
499 import os
500+import pathlib
501 import re
502 import subprocess
503 import time
504@@ -205,6 +206,11 @@ def is_active_esm(series: str) -> bool:
505
506
507 @lru_cache(maxsize=None)
508+def is_current_series_active_esm() -> bool:
509+ return is_active_esm(get_platform_info()["series"])
510+
511+
512+@lru_cache(maxsize=None)
513 def is_container(run_path: str = "/run") -> bool:
514 """Checks to see if this code running in a container of some sort"""
515
516@@ -350,6 +356,13 @@ def load_file(filename: str, decode: bool = True) -> str:
517 return content.decode("utf-8")
518
519
520+def create_file(filename: str, mode: int = 0o644) -> None:
521+ logging.debug("Creating file: %s", filename)
522+ os.makedirs(os.path.dirname(filename), exist_ok=True)
523+ pathlib.Path(filename).touch()
524+ os.chmod(filename, mode)
525+
526+
527 def write_file(filename: str, content: str, mode: int = 0o644) -> None:
528 """Write content to the provided filename encoding it if necessary.
529
530diff --git a/uaclient/tests/test_actions.py b/uaclient/tests/test_actions.py
531index 6f77d7f..12c05f1 100644
532--- a/uaclient/tests/test_actions.py
533+++ b/uaclient/tests/test_actions.py
534@@ -1,8 +1,10 @@
535+import logging
536+
537 import mock
538 import pytest
539
540 from uaclient import exceptions, messages
541-from uaclient.actions import attach_with_token, auto_attach
542+from uaclient.actions import attach_with_token, auto_attach, collect_logs
543 from uaclient.exceptions import ContractAPIError, NonAutoAttachImageError
544 from uaclient.tests.test_cli_auto_attach import fake_instance_factory
545
546@@ -141,3 +143,36 @@ class TestAutoAttach:
547 auto_attach(cfg, fake_instance_factory())
548
549 assert unexpected_error == excinfo.value
550+
551+
552+@mock.patch("uaclient.actions._write_command_output_to_file")
553+class TestCollectLogs:
554+ @pytest.mark.parametrize("caplog_text", [logging.WARNING], indirect=True)
555+ @mock.patch("os.getuid")
556+ @mock.patch("uaclient.system.write_file")
557+ @mock.patch("uaclient.system.load_file")
558+ @mock.patch("uaclient.actions._get_state_files")
559+ @mock.patch("glob.glob")
560+ def test_collect_logs_invalid_file(
561+ self,
562+ m_glob,
563+ m_get_state_files,
564+ m_load_file,
565+ m_write_file,
566+ m_getuid,
567+ m_write_cmd,
568+ caplog_text,
569+ ):
570+ m_get_state_files.return_value = ["a", "b"]
571+ m_load_file.side_effect = [UnicodeError("test"), "test"]
572+ m_getuid.return_value = 1
573+ m_glob.return_value = []
574+
575+ with mock.patch("os.path.isfile", return_value=True):
576+ collect_logs(cfg=mock.MagicMock(), output_dir="test")
577+
578+ assert 2 == m_load_file.call_count
579+ assert [mock.call("a"), mock.call("b")] == m_load_file.call_args_list
580+ assert 1 == m_write_file.call_count
581+ assert [mock.call("test/b", "test")] == m_write_file.call_args_list
582+ assert "Failed to load file: a\n" in caplog_text()
583diff --git a/uaclient/tests/test_cli_config_set.py b/uaclient/tests/test_cli_config_set.py
584index 66aaf82..d8a7c49 100644
585--- a/uaclient/tests/test_cli_config_set.py
586+++ b/uaclient/tests/test_cli_config_set.py
587@@ -16,7 +16,8 @@ positional arguments:
588 must be one of: http_proxy, https_proxy, apt_http_proxy,
589 apt_https_proxy, ua_apt_http_proxy, ua_apt_https_proxy,
590 global_apt_http_proxy, global_apt_https_proxy,
591- update_messaging_timer, update_status_timer, metering_timer
592+ update_messaging_timer, update_status_timer, metering_timer,
593+ apt_news
594
595 Flags:
596 -h, --help show this help message and exit
597diff --git a/uaclient/tests/test_cli_config_show.py b/uaclient/tests/test_cli_config_show.py
598index d4582fd..ebf760c 100644
599--- a/uaclient/tests/test_cli_config_show.py
600+++ b/uaclient/tests/test_cli_config_show.py
601@@ -117,6 +117,7 @@ global_apt_https_proxy http://global_apt_https_proxy
602 update_messaging_timer None
603 update_status_timer None
604 metering_timer None
605+apt_news True
606 """
607 == out
608 )
609diff --git a/uaclient/tests/test_cli_config_unset.py b/uaclient/tests/test_cli_config_unset.py
610index 115bc86..42c3625 100644
611--- a/uaclient/tests/test_cli_config_unset.py
612+++ b/uaclient/tests/test_cli_config_unset.py
613@@ -15,7 +15,7 @@ positional arguments:
614 http_proxy, https_proxy, apt_http_proxy, apt_https_proxy,
615 ua_apt_http_proxy, ua_apt_https_proxy, global_apt_http_proxy,
616 global_apt_https_proxy, update_messaging_timer,
617- update_status_timer, metering_timer
618+ update_status_timer, metering_timer, apt_news
619
620 Flags:
621 -h, --help show this help message and exit
622diff --git a/uaclient/tests/test_config.py b/uaclient/tests/test_config.py
623index bd8a49e..d3b493c 100644
624--- a/uaclient/tests/test_config.py
625+++ b/uaclient/tests/test_config.py
626@@ -295,6 +295,7 @@ UA_CFG_DICT = {
627 "ua_config": {
628 "apt_http_proxy": None,
629 "apt_https_proxy": None,
630+ "apt_news": True,
631 "global_apt_http_proxy": None,
632 "global_apt_https_proxy": None,
633 "ua_apt_http_proxy": None,
634@@ -316,7 +317,9 @@ class TestUAConfigKeys:
635 ):
636 """Getters and settings are available fo UA_CONFIGURABLE_KEYS."""
637 cfg = FakeConfig()
638- assert None is getattr(cfg, attr_name, None)
639+ assert UA_CFG_DICT["ua_config"][attr_name] == getattr(
640+ cfg, attr_name, None
641+ )
642 cfg_non_members = ("apt_http_proxy", "apt_https_proxy")
643 if attr_name not in cfg_non_members:
644 setattr(cfg, attr_name, attr_name + "value")
645diff --git a/uaclient/version.py b/uaclient/version.py
646index 54776f6..c9b72ab 100644
647--- a/uaclient/version.py
648+++ b/uaclient/version.py
649@@ -18,7 +18,7 @@ from uaclient.defaults import CANDIDATE_CACHE_PATH, UAC_TMP_PATH
650 from uaclient.exceptions import ProcessExecutionError
651 from uaclient.system import subp
652
653-__VERSION__ = "27.11.2"
654+__VERSION__ = "27.11.3"
655 PACKAGED_VERSION = "@@PACKAGED_VERSION@@"
656
657 CANDIDATE_REGEX = r"Candidate: (?P<candidate>.*?)\n"

Subscribers

People subscribed via source and target branches

to status/vote changes: