Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oracular update for apt-hook #3365

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
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
167 changes: 122 additions & 45 deletions apt-hook/json-hook.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <cstdio>
#include <ext/stdio_filebuf.h>
#include <fstream>
#include <iostream>
Expand Down Expand Up @@ -98,6 +99,32 @@ bool version_from_origin_and_archive_ends_with(json_object *version, std::string
return false;
}

release_info get_release_info() {
release_info info = {"", "", false};
std::ifstream machine_series_file("/etc/os-release");
if (machine_series_file.is_open()) {
std::string currentLine;
while(std::getline(machine_series_file, currentLine)) {
size_t position = currentLine.find("="); // Find position of equals sign as separator
std::string key = currentLine.substr(0, position);
std::string value = currentLine.substr(position + 1);

if (!value.empty() && value.front() == '"' && value.back() == '"') {
value = value.substr(1, value.length() - 2);
}

if (key=="VERSION_ID") {
info.release = value;
} else if (key == "VERSION_CODENAME") {
info.series = value;
} else if (key == "PRETTY_NAME" && value.find("LTS") != std::string::npos) {
info.is_lts = true;
}
}
}
return info;
}

bool count_security_packages_from_apt_stats_json(json_object *stats, security_package_counts &result) {
bool has_key = false;
result.standard = 0;
Expand Down Expand Up @@ -193,7 +220,7 @@ bool collect_pro_packages_from_pre_prompt_json(json_object *pre_prompt, std::vec
continue;
}
std::string package_mode(json_object_get_string(tmp));

has_key = json_object_object_get_ex(package, "name", &tmp);
if (!has_key) {
continue;
Expand Down Expand Up @@ -234,35 +261,50 @@ bool collect_pro_packages_from_pre_prompt_json(json_object *pre_prompt, std::vec
}

#define MAX_COUNT_MESSAGE_LEN 256
std::string create_count_message(security_package_counts &counts) {
std::string create_count_message(security_package_counts &counts, release_info info) {
char buf[MAX_COUNT_MESSAGE_LEN] = {0};
std::string lts_text = info.is_lts ? "LTS " : "";

if (counts.esm_apps == 0) {
if (counts.esm_infra == 0) {
if (counts.standard == 0) {
return "";
} else if (counts.standard == 1) {
return std::string(gettext("1 standard LTS security update"));
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("1 standard %ssecurity update"),
lts_text.c_str()
);
return std::string(buf);
} else if (counts.standard > 1) {
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("%lu standard LTS security updates"),
counts.standard
gettext("%lu standard %ssecurity updates"),
counts.standard,
lts_text.c_str()
);
return std::string(buf);
}
} else if (counts.esm_infra == 1) {
if (counts.standard == 0) {
return std::string(gettext("1 esm-infra security update"));
} else if (counts.standard == 1) {
return std::string(gettext("1 standard LTS security update and 1 esm-infra security update"));
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("1 standard %ssecurity update and 1 esm-infra security update"),
lts_text.c_str()
);
return std::string(buf);
} else if (counts.standard > 1) {
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("%lu standard LTS security updates and 1 esm-infra security update"),
counts.standard
gettext("%lu standard %ssecurity updates and 1 esm-infra security update"),
counts.standard,
lts_text.c_str()
);
return std::string(buf);
}
Expand All @@ -279,16 +321,18 @@ std::string create_count_message(security_package_counts &counts) {
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("1 standard LTS security update and %lu esm-infra security updates"),
gettext("1 standard %ssecurity update and %lu esm-infra security updates"),
lts_text.c_str(),
counts.esm_infra
);
return std::string(buf);
} else if (counts.standard > 1) {
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("%lu standard LTS security updates and %lu esm-infra security updates"),
gettext("%lu standard %ssecurity updates and %lu esm-infra security updates"),
counts.standard,
lts_text.c_str(),
counts.esm_infra
);
return std::string(buf);
Expand All @@ -299,27 +343,46 @@ std::string create_count_message(security_package_counts &counts) {
if (counts.standard == 0) {
return std::string(gettext("1 esm-apps security update"));
} else if (counts.standard == 1) {
return std::string(gettext("1 standard LTS security update and 1 esm-apps security update"));
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("1 standard %ssecurity update and 1 esm-apps security update"),
lts_text.c_str()
);
return std::string(buf);
} else if (counts.standard > 1) {
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("%lu standard LTS security updates and 1 esm-apps security update"),
counts.standard
gettext("%lu standard %ssecurity updates and 1 esm-apps security update"),
counts.standard,
lts_text.c_str()
);
return std::string(buf);
}
} else if (counts.esm_infra == 1) {
if (counts.standard == 0) {
return std::string(gettext("1 esm-infra security update and 1 esm-apps security update"));
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("1 esm-infra security update and 1 esm-apps security update")
);
return std::string(buf);
} else if (counts.standard == 1) {
return std::string(gettext("1 standard LTS security update, 1 esm-infra security update and 1 esm-apps security update"));
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("1 standard %ssecurity update, 1 esm-infra security update and 1 esm-apps security update"),
lts_text.c_str()
);
return std::string(buf);
} else if (counts.standard > 1) {
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("%lu standard LTS security updates, 1 esm-infra security update and 1 esm-apps security update"),
counts.standard
gettext("%lu standard %ssecurity updates, 1 esm-infra security update and 1 esm-apps security update"),
counts.standard,
lts_text.c_str()
);
return std::string(buf);
}
Expand All @@ -336,16 +399,18 @@ std::string create_count_message(security_package_counts &counts) {
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("1 standard LTS security update, %lu esm-infra security updates and 1 esm-apps security update"),
gettext("1 standard %ssecurity update, %lu esm-infra security updates and 1 esm-apps security update"),
lts_text.c_str(),
counts.esm_infra
);
return std::string(buf);
} else if (counts.standard > 1) {
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("%lu standard LTS security updates, %lu esm-infra security updates and 1 esm-apps security update"),
gettext("%lu standard %ssecurity updates, %lu esm-infra security updates and 1 esm-apps security update"),
counts.standard,
lts_text.c_str(),
counts.esm_infra
);
return std::string(buf);
Expand All @@ -365,16 +430,18 @@ std::string create_count_message(security_package_counts &counts) {
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("1 standard LTS security update and %lu esm-apps security updates"),
gettext("1 standard %ssecurity update and %lu esm-apps security updates"),
lts_text.c_str(),
counts.esm_apps
);
return std::string(buf);
} else if (counts.standard > 1) {
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("%lu standard LTS security updates and %lu esm-apps security updates"),
gettext("%lu standard %ssecurity updates and %lu esm-apps security updates"),
counts.standard,
lts_text.c_str(),
counts.esm_apps
);
return std::string(buf);
Expand All @@ -392,16 +459,18 @@ std::string create_count_message(security_package_counts &counts) {
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("1 standard LTS security update, 1 esm-infra security update and %lu esm-apps security updates"),
gettext("1 standard %ssecurity update, 1 esm-infra security update and %lu esm-apps security updates"),
lts_text.c_str(),
counts.esm_apps
);
return std::string(buf);
} else if (counts.standard > 1) {
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("%lu standard LTS security updates, 1 esm-infra security update and %lu esm-apps security updates"),
gettext("%lu standard %ssecurity updates, 1esm-infra security update and %lu esm-apps security updates"),
counts.standard,
lts_text.c_str(),
counts.esm_apps
);
return std::string(buf);
Expand All @@ -420,7 +489,8 @@ std::string create_count_message(security_package_counts &counts) {
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("1 standard LTS security update, %lu esm-infra security updates and %lu esm-apps security updates"),
gettext("1 standard %ssecurity update, %lu esm-infra security updates and %lu esm-apps security updates"),
lts_text.c_str(),
counts.esm_infra,
counts.esm_apps
);
Expand All @@ -429,8 +499,9 @@ std::string create_count_message(security_package_counts &counts) {
std::snprintf(
buf,
MAX_COUNT_MESSAGE_LEN,
gettext("%lu standard LTS security updates, %lu esm-infra security updates and %lu esm-apps security updates"),
gettext("%lu standard %ssecuriy updates, %lu esm-infra security updates and %lu esm-apps security updates"),
counts.standard,
lts_text.c_str(),
counts.esm_infra,
counts.esm_apps
);
Expand Down Expand Up @@ -463,24 +534,21 @@ CloudID get_cloud_id() {

enum ESMInfraSeries {NOT_ESM_INFRA, XENIAL, BIONIC};

ESMInfraSeries get_esm_infra_series() {
std::ifstream os_release_file("/etc/os-release");
ESMInfraSeries get_esm_infra_series(release_info info) {
ESMInfraSeries ret = NOT_ESM_INFRA;
if (os_release_file.is_open()) {
std::string os_release_str((std::istreambuf_iterator<char>(os_release_file)), (std::istreambuf_iterator<char>()));
if (os_release_str.find("xenial") != os_release_str.npos) {
if (info.release != "") {
if (info.series == "xenial") {
ret = XENIAL;
} else if (os_release_str.find("bionic") != os_release_str.npos) {
} else if (info.series == "bionic") {
ret = BIONIC;
}
os_release_file.close();
}
return ret;
}

void print_learn_more_with_context() {
void print_learn_more_with_context(release_info info) {
CloudID cloud_id = get_cloud_id();
ESMInfraSeries esm_infra_series = get_esm_infra_series();
ESMInfraSeries esm_infra_series = get_esm_infra_series(info);

if (esm_infra_series == XENIAL) {
if (cloud_id == AZURE) {
Expand Down Expand Up @@ -563,8 +631,11 @@ void print_learn_more_with_context() {
return;
}

void print_package_names(std::vector<std::string> package_names) {
void print_package_names(std::vector<std::string> package_names, release_info info) {
std::string curr_line = " ";
if (info.release != "" && info.release >= "24.10") {
curr_line = " ";
}
for (std::string &name : package_names) {
if ((curr_line.length() + 1 + name.length()) >= 79) {
std::cout << curr_line << std::endl;
Expand All @@ -577,7 +648,7 @@ void print_package_names(std::vector<std::string> package_names) {
}
}

void print_esm_packages(ESMType esm_type, std::vector<std::string> package_names) {
void print_esm_packages(ESMType esm_type, std::vector<std::string> package_names, release_info info) {
if (esm_type == APPS) {
printf(
ngettext(
Expand All @@ -598,20 +669,20 @@ void print_esm_packages(ESMType esm_type, std::vector<std::string> package_names
printf("\n");
}

print_package_names(package_names);
print_package_names(package_names, info);

print_learn_more_with_context();
print_learn_more_with_context(info);
}

void print_expired_pro_packages(std::vector<std::string> package_names) {
void print_expired_pro_packages(std::vector<std::string> package_names, release_info info) {
printf(
gettext(
"The following packages will fail to download because your Ubuntu Pro subscription has expired"
)
);
printf("\n");

print_package_names(package_names);
print_package_names(package_names, info);

printf(
gettext(
Expand Down Expand Up @@ -686,13 +757,19 @@ int run()
std::cerr << "pro-hook: failed to read hook msg" << std::endl;
return 0;
}
release_info info = get_release_info();
if (hook_req.method == "org.debian.apt.hooks.install.statistics") {
security_package_counts counts;
success = count_security_packages_from_apt_stats_json(hook_req.params, counts);
if (success) {
std::string message = create_count_message(counts);
std::string message = create_count_message(counts, info);
if (message != "") {
std::cout << message << std::endl;
if (info.release != "" && info.release >= "24.10") {
std::cout << " " << message << std::endl;
}
else {
std::cout << message << std::endl;
}
dheyay marked this conversation as resolved.
Show resolved Hide resolved
}
}
} else if (hook_req.method == "org.debian.apt.hooks.install.pre-prompt") {
Expand All @@ -701,9 +778,9 @@ int run()
success = get_potential_esm_updates(esm_updates);
if (success) {
if (!esm_updates.infra_packages.empty()) {
print_esm_packages(INFRA, esm_updates.infra_packages);
print_esm_packages(INFRA, esm_updates.infra_packages, info);
} else if (!esm_updates.apps_packages.empty()) {
print_esm_packages(APPS, esm_updates.apps_packages);
print_esm_packages(APPS, esm_updates.apps_packages, info);
}
}

Expand All @@ -720,7 +797,7 @@ int run()
std::vector<std::string> expired_packages;
success = collect_pro_packages_from_pre_prompt_json(hook_req.params, &expired_packages);
if (success && expired_packages.size() > 0) {
print_expired_pro_packages(expired_packages);
print_expired_pro_packages(expired_packages, info);
}
}
}
Expand Down
Loading
Loading