Skip to content

status subscription: extend output#1312

Merged
arogge merged 7 commits intobareos:masterfrom
joergsteffens:dev/joergs/master/subscription-core
Dec 8, 2022
Merged

status subscription: extend output#1312
arogge merged 7 commits intobareos:masterfrom
joergsteffens:dev/joergs/master/subscription-core

Conversation

@joergsteffens
Copy link
Member

@joergsteffens joergsteffens commented Nov 15, 2022

While working on #1280 some improvements to the status subscription command did come up and are now handled in this separate PR.

  • improve the JSON output, reducing the depth of the structure and make it better understand- and parseable
  • add information Bareos version (also in case the calculation of units will change with other versions), current date and simple checksum.
  • add ACL test.

Please check

  • Short description and the purpose of this PR is present above this paragraph
  • Your name is present in the AUTHORS file (optional)

If you have any questions or problems, please give a comment in the PR.

Helpful documentation and best practices

Checklist for the reviewer of the PR (will be processed by the Bareos team)

General
  • PR name is meaningful
  • Purpose of the PR is understood
  • Commit descriptions are understandable and well formatted
  • Check backport line
  • Is the PR title usable as CHANGELOG entry?
  • Separate commit for CHANGELOG.md ("update CHANGELOG.md"). The PR number is correct.
Source code quality
  • Source code changes are understandable
  • Variable and function names are meaningful
  • Code comments are correct (logically and spelling)
  • Required documentation changes are present and part of the PR
  • bareos-check-sources --since-merge does not report any problems
Tests
  • Decision taken that a test is required (if not, then remove this paragraph)
  • The choice of the type of test (unit test or systemtest) is reasonable
  • Testname matches exactly what is being tested
  • On a fail, output of the test leads quickly to the origin of the fault

Copy link
Member

@arogge arogge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty good, but we can probably do better :)

Comment on lines +73 to +76
if (verbose) {
Mmsg(errmsg, _("Query failed: %s\n"), sql_strerror());
sendit->Decoration(errmsg);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a functional change that may not be desired.
The caller could call us with verbose set to false, resulting in errmsg still being set and using other means of displaying the message to the user.

std::string compute_hash(const std::string& unhashed,
const std::string& digestname)
{
std::stringstream string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please don't name variables like a type, especially don't name a variable like a different type (i.e. this is a stringstream and you named it string)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

EVP_MD_CTX_destroy(context);
}
}
return string.str();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so on any error, you'll just get an empty string.
That doesn't feel like great error handling.
Maybe we should use an std::optional to handle errors nicer.

unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int lengthOfHash = 0;
if (EVP_DigestFinal_ex(context, hash, &lengthOfHash)) {
string << "{" << digestname << "}";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should probably get the digest name back from OpenSSL, so the string value is fixed, even if you pass digestname as "ShA512" or something like that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

string << "{" << digestname << "}";
string << std::hex << std::setw(2) << std::setfill('0');
for (unsigned int i = 0; i < lengthOfHash; ++i) {
string << (int)hash[i];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should prefer C++-style casts like static_cast<int>() in this case over C style casts to avoid casting const away accidentally.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

PoolMem subscriptions(PM_MESSAGE);
PoolMem query(PM_MESSAGE);
OutputFormatter output_text
= OutputFormatter(pm_append, (void*)&subscriptions, nullptr, nullptr);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

casts to void* are implicit and c-style casts are evil.

Suggested change
= OutputFormatter(pm_append, (void*)&subscriptions, nullptr, nullptr);
= OutputFormatter(pm_append, &subscriptions, nullptr, nullptr);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

return true;
}

std::string get_subscription_status_signature_source_text(UaContext* ua,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're only using ua->db, so maybe consider BareosDb* instead of UaContext* or maybe BareosDb&.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also using ua->jcr. So either I leave it like this, or I've to add another parameter jcr. I opt for leave it like this.

description, verbose);
}

bool BareosDb::ListOneRowSqlQuery(JobControlRecord* jcr,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of adding a whole new function, we could consider adding another defaulted parameter to ListSqlQuery() that will make it use ObjectStart()/ObjectEnd() if SqlNumRows() == 1.

Optimal would be a custom enum class with reasonable symbolic names so that you're passing something like CollapseMode::Collapse and default it to CollapseMode::NoCollapse instead of just adding a bool where you have to look up what it does.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

std::string signature_source
= get_subscription_status_signature_source_text(ua, now);
std::string hash = compute_hash(signature_source.c_str());
ua->send->ObjectKeyValue("signature", "Signature: ", hash.c_str(), "%s\n");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really wouldn't call it a signature, it is just a hash or checksum, so we should probably name it as such.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I named it Checksum now.

ua->send->ObjectKeyValue("binary-info",
"Binary info: ", kBareosVersionStrings.BinaryInfo,
"%s\n");
ua->send->ObjectKeyValue("date", "Date: ", now, "%s\n");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is called date, but contains the current time.
Maybe something like "report-time" and "Report time:" is more reasonable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

@joergsteffens
Copy link
Member Author

I addressed all mentioned suggestions. Without new feedback, the only I maybe can address is replacing compute_hash by the already existing function. Anyhow, I'll not have the time for this before next week. But maybe this is not even required, as this function also works on all our supported platforms.

Copy link
Member

@arogge arogge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a few observations, but no objections. Looks good to me now!

Comment on lines +564 to +568
std::optional<std::string> checksum = compute_hash(checksum_source.c_str());
if (checksum) {
ua->send->ObjectKeyValue("checksum",
"Checksum: ", checksum.value().c_str(), "%s\n");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • i would probably have used auto instead of std::optional<std::string> here.
  • compute_hash() takes a const std::string& as first parameter. You're passing the underlying const char* of your existing std::string to it, which will lead to an implicit conversion to std::string() which implies another copy. Just passing the std::string would be better
  • there are two ways to get the value out of a std::optional: calling value() or operator*/operator->. With value() you get a check that there is a value in your optional (and an exception if there is none), while with the operators behaviour is undefined if there is no value. As you checked that there is a value, you can safely use the operators, simplifying checksum.value().c_str() to just checksum->c_str().

frb121 and others added 3 commits December 8, 2022 10:12
Instead of the command ACL "configure",
unrestriced access to Clients, Jobs and Filesets is required,
as these are the information that the command really uses.
This can result is much better read- and parseable results.
@joergsteffens joergsteffens force-pushed the dev/joergs/master/subscription-core branch from 6b752d9 to be7080d Compare December 8, 2022 15:02
In case the calculation of subscription will change in the future,
adding version information will help to determine how the subscription
counting is done at that time.
@arogge arogge force-pushed the dev/joergs/master/subscription-core branch 2 times, most recently from 2614462 to 592c5db Compare December 8, 2022 16:59
@arogge arogge merged commit 787ba1e into bareos:master Dec 8, 2022
@joergsteffens joergsteffens deleted the dev/joergs/master/subscription-core branch October 11, 2023 08:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants