-
Notifications
You must be signed in to change notification settings - Fork 61
C API for UptaneCycle and campaigns #1263
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#ifndef AKTUALIZR_LIBAKTUALIZRC_H | ||
#define AKTUALIZR_LIBAKTUALIZRC_H | ||
|
||
#ifdef __cplusplus | ||
#include "primary/aktualizr.h" | ||
|
||
using Campaign = campaign::Campaign; | ||
|
||
extern "C" { | ||
#else | ||
typedef struct Aktualizr Aktualizr; | ||
typedef struct Campaign Campaign; | ||
#endif | ||
|
||
Aktualizr *Aktualizr_create(const char *config_path); | ||
int Aktualizr_initialize(Aktualizr *a); | ||
int Aktualizr_uptane_cycle(Aktualizr *a); | ||
void Aktualizr_destroy(Aktualizr *a); | ||
|
||
Campaign *Aktualizr_campaign_check(Aktualizr *a); | ||
int Aktualizr_campaign_accept(Aktualizr *a, Campaign *c); | ||
int Aktualizr_campaign_postpone(Aktualizr *a, Campaign *c); | ||
int Aktualizr_campaign_decline(Aktualizr *a, Campaign *c); | ||
void Aktualizr_campaign_free(Campaign *c); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif //AKTUALIZR_LIBAKTUALIZR_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
SET(TARGET_NAME aktualizr-c) | ||
SET(SOURCES libaktualizr-c.cc) | ||
|
||
add_library(${TARGET_NAME} SHARED ${SOURCES}) | ||
target_include_directories(${TARGET_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include) | ||
target_link_libraries(${TARGET_NAME} PRIVATE aktualizr_static_lib ${AKTUALIZR_EXTERNAL_LIBS}) | ||
|
||
aktualizr_source_file_checks(${SOURCES}) | ||
|
||
add_subdirectory(test) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#include "libaktualizr-c.h" | ||
|
||
Aktualizr *Aktualizr_create(const char *config_path) { | ||
Aktualizr *a; | ||
try { | ||
Config cfg(config_path); | ||
a = new Aktualizr(cfg); | ||
} catch (const std::exception &e) { | ||
std::cerr << "Aktualizr_create exception: " << e.what() << std::endl; | ||
return nullptr; | ||
} | ||
return a; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe, there will be a need/requirement to return some status/error code to am app using the C version of libaktualizr, otherwise the only way to find out what went wrong is by parsing stderr. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mike-sul Absolutely. But first, we'll need to make sure that exceptions thrown by libaktualizr are consistent and meaningful. I plan to work on that next. |
||
} | ||
|
||
int Aktualizr_initialize(Aktualizr *a) { | ||
try { | ||
a->Initialize(); | ||
} catch (const std::exception &e) { | ||
std::cerr << "Aktualizr_initialize exception: " << e.what() << std::endl; | ||
return -1; | ||
} | ||
return 0; | ||
} | ||
|
||
int Aktualizr_uptane_cycle(Aktualizr *a) { | ||
try { | ||
a->UptaneCycle(); | ||
} catch (const std::exception &e) { | ||
std::cerr << "Uptane cycle exception: " << e.what() << std::endl; | ||
return -1; | ||
} | ||
return 0; | ||
} | ||
|
||
void Aktualizr_destroy(Aktualizr *a) { delete a; } | ||
|
||
Campaign *Aktualizr_campaign_check(Aktualizr *a) { | ||
try { | ||
auto r = a->CampaignCheck().get(); | ||
if (!r.campaigns.empty()) { | ||
// We don't support multiple campaigns at the moment | ||
return new Campaign(r.campaigns[0]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it fair to assume there will never be multiple campaigns? It would indeed be confusing if there were, but a comment to state the assumption might be worthwhile. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not supported at the moment, so I think it's worth keeping it simple here. I'll add a comment. |
||
} | ||
} catch (const std::exception &e) { | ||
std::cerr << "Campaign check exception: " << e.what() << std::endl; | ||
return nullptr; | ||
} | ||
return nullptr; | ||
} | ||
int Aktualizr_campaign_accept(Aktualizr *a, Campaign *c) { | ||
try { | ||
a->CampaignControl(c->id, campaign::Cmd::Accept).get(); | ||
} catch (const std::exception &e) { | ||
std::cerr << "Campaign accept exception: " << e.what() << std::endl; | ||
return -1; | ||
} | ||
return 0; | ||
} | ||
int Aktualizr_campaign_postpone(Aktualizr *a, Campaign *c) { | ||
try { | ||
a->CampaignControl(c->id, campaign::Cmd::Postpone).get(); | ||
} catch (const std::exception &e) { | ||
std::cerr << "Campaign postpone exception: " << e.what() << std::endl; | ||
return -1; | ||
} | ||
return 0; | ||
} | ||
int Aktualizr_campaign_decline(Aktualizr *a, Campaign *c) { | ||
try { | ||
a->CampaignControl(c->id, campaign::Cmd::Decline).get(); | ||
} catch (const std::exception &e) { | ||
std::cerr << "Campaign decline exception: " << e.what() << std::endl; | ||
return -1; | ||
} | ||
return 0; | ||
} | ||
void Aktualizr_campaign_free(Campaign *c) { delete c; } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
SET(TARGET_NAME api-test) | ||
SET(SOURCES api-test.c) | ||
|
||
add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL ${SOURCES}) | ||
add_dependencies(build_tests ${TARGET_NAME}) | ||
target_link_libraries(${TARGET_NAME} aktualizr-c) | ||
|
||
aktualizr_source_file_checks(${SOURCES}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
#include "libaktualizr-c.h" | ||
|
||
int main(int argc, char **argv) { | ||
Aktualizr *a; | ||
Campaign *c; | ||
int err; | ||
|
||
if (argc != 2) { | ||
fprintf(stderr, "Missing config file\nUsage:\n\t%s CONFIG_FILE\n", argv[0]); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
a = Aktualizr_create(argv[1]); | ||
if (!a) { | ||
return EXIT_FAILURE; | ||
} | ||
|
||
err = Aktualizr_initialize(a); | ||
if (err) { | ||
return EXIT_FAILURE; | ||
} | ||
|
||
c = Aktualizr_campaign_check(a); | ||
if (c) { | ||
printf("Accepting running campaign\n"); | ||
err = Aktualizr_campaign_accept(a, c); | ||
Aktualizr_campaign_free(c); | ||
if (err) { | ||
return EXIT_FAILURE; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will the aktualizr instance be properly tear-downed and freed in this case as well as in case of line #23 ? Or it's not important taking into account that the process is going to die anyway ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It won't, I forgot how to write proper C ;) But I'm rewriting this piece anyway |
||
} | ||
} | ||
|
||
err = Aktualizr_uptane_cycle(a); | ||
if (err) { | ||
return EXIT_FAILURE; | ||
} | ||
|
||
Aktualizr_destroy(a); | ||
|
||
return EXIT_SUCCESS; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a bit annoying that we have to pass an Aktualizr instance to all of these. Would be handy if Campaign contained a pointer. But that might need changes in the C++ object, don't know if we want that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see no problem in this, tbh. That's pretty much idiomatic C and is equivalent to
Aktualizr->CampaignAccept(Campaign *c)
. If we do just a single arg here, I would expect our C++ API to also change toCampaign->Accept()
. I'm not sure if it makes it nicer, though.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I think you're right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thought, maybe it's not a bad thing to make those calls members of Campaign object. This way, we would prevent passing a campaign_id that belongs to another Aktualizr instance (a hypothetical situation, but still). WDYT, @lbonn @patrickvacek @mike-sul ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it doesn't require changes to the C++ code, then that seems like the way to go. Even if it does, that seems to me to be a slightly better way to go.