From 91f4347ef7bde17418b365ed3a97a752fe65bd50 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Dec 2014 19:42:27 +0100 Subject: [PATCH] import: rename 'poll-dck' to 'pull-dkr' I figure "pull-dck" is not a good name, given that one could certainly read the verb in a way that might be funny for 16year-olds. ;-) Also, don't hardcode the index URL to use, make it runtime and configure time configurable instead. --- Makefile.am | 4 +- TODO | 2 +- configure.ac | 9 + src/import/{import-dck.c => import-dkr.c} | 221 ++++++++++++---------- src/import/{import-dck.h => import-dkr.h} | 21 +- src/import/import.c | 41 ++-- 6 files changed, 174 insertions(+), 124 deletions(-) rename src/import/{import-dck.c => import-dkr.c} (83%) rename src/import/{import-dck.h => import-dkr.h} (58%) diff --git a/Makefile.am b/Makefile.am index baa1398a41..904517ffa6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5131,8 +5131,8 @@ bin_PROGRAMS += \ systemd_import_SOURCES = \ src/import/import.c \ - src/import/import-dck.c \ - src/import/import-dck.h \ + src/import/import-dkr.c \ + src/import/import-dkr.h \ src/import/curl-util.c \ src/import/curl-util.h \ src/import/aufs-util.c \ diff --git a/TODO b/TODO index fedcf59182..587a692959 100644 --- a/TODO +++ b/TODO @@ -51,7 +51,7 @@ Features: * make "machinectl login" use a new machined call AllocateMachinePty() or so to get a pty in a machine. That would open up logins to unprivileged clients -* add transparent btrfs pool in a loopback file in /var if btrfs operations (such as systemd-import pull-dck) are used and /var is not a btrfs file system +* add transparent btrfs pool in a loopback file in /var if btrfs operations (such as systemd-import pull-dkr) are used and /var is not a btrfs file system * machined: open up certain commands to unprivileged clients via polkit diff --git a/configure.ac b/configure.ac index 9296c25dbb..0e7216638c 100644 --- a/configure.ac +++ b/configure.ac @@ -1316,6 +1316,14 @@ AC_ARG_ENABLE([split-usr], enable_split_usr=no ])]) +AC_ARG_WITH([dkr-index-url], + [AS_HELP_STRING([--dkr-index-url=URL], [Specify the default index URL to use for image downloads])], + [DEFAULT_DKR_INDEX_URL="\"$withval\""], + [DEFAULT_DKR_INDEX_URL="NULL"]) + +AC_DEFINE_UNQUOTED(DEFAULT_DKR_INDEX_URL, [$DEFAULT_DKR_INDEX_URL], [Default index URL to use for image downloads]) +AC_SUBST(DEFAULT_DKR_INDEX_URL) + AS_IF([test "x${enable_split_usr}" = "xyes"], [ AC_DEFINE(HAVE_SPLIT_USR, 1, [Define if /bin, /sbin aren't symlinks into /usr]) ]) @@ -1478,6 +1486,7 @@ AC_MSG_RESULT([ Maximum System UID: ${SYSTEM_UID_MAX} Maximum System GID: ${SYSTEM_GID_MAX} Certificate root: ${CERTIFICATEROOT} + Default dkr Index ${DEFAULT_DKR_INDEX_URL} CFLAGS: ${OUR_CFLAGS} ${CFLAGS} CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS} diff --git a/src/import/import-dck.c b/src/import/import-dkr.c similarity index 83% rename from src/import/import-dck.c rename to src/import/import-dkr.c index adb0c90175..e2910f940f 100644 --- a/src/import/import-dck.c +++ b/src/import/import-dkr.c @@ -27,9 +27,10 @@ #include "json.h" #include "strv.h" #include "curl-util.h" -#include "import-dck.h" +#include "import-dkr.h" #include "btrfs-util.h" #include "aufs-util.h" +#include "utf8.h" /* TODO: - convert json bits @@ -37,25 +38,25 @@ - fall back to btrfs loop pool device */ -typedef struct DckImportJob DckImportJob; -typedef struct DckImportName DckImportName; +typedef struct DkrImportJob DkrImportJob; +typedef struct DkrImportName DkrImportName; -typedef enum DckImportJobType { - DCK_IMPORT_JOB_IMAGES, - DCK_IMPORT_JOB_TAGS, - DCK_IMPORT_JOB_ANCESTRY, - DCK_IMPORT_JOB_JSON, - DCK_IMPORT_JOB_LAYER, -} DckImportJobType; +typedef enum DkrImportJobType { + DKR_IMPORT_JOB_IMAGES, + DKR_IMPORT_JOB_TAGS, + DKR_IMPORT_JOB_ANCESTRY, + DKR_IMPORT_JOB_JSON, + DKR_IMPORT_JOB_LAYER, +} DkrImportJobType; -struct DckImportJob { - DckImport *import; - DckImportJobType type; +struct DkrImportJob { + DkrImport *import; + DkrImportJobType type; bool done; char *url; - Set *needed_by; /* DckImport Name objects */ + Set *needed_by; /* DkrImport Name objects */ CURL *curl; struct curl_slist *request_header; @@ -72,15 +73,16 @@ struct DckImportJob { FILE *tar_stream; }; -struct DckImportName { - DckImport *import; +struct DkrImportName { + DkrImport *import; + char *index_url; char *name; char *tag; char *id; char *local; - DckImportJob *job_images, *job_tags, *job_ancestry, *job_json, *job_layer; + DkrImportJob *job_images, *job_tags, *job_ancestry, *job_json, *job_layer; char **ancestry; unsigned current_ancestry; @@ -88,19 +90,18 @@ struct DckImportName { bool force_local; }; -struct DckImport { +struct DkrImport { sd_event *event; CurlGlue *glue; Hashmap *names; Hashmap *jobs; - dck_import_on_finished on_finished; + dkr_import_on_finished on_finished; void *userdata; }; #define PROTOCOL_PREFIX "https://" -#define INDEX_HOST "index.do" /* the URL we get the data from */ "cker.io" #define HEADER_TOKEN "X-Do" /* the HTTP header for the auth token */ "cker-Token:" #define HEADER_REGISTRY "X-Do" /*the HTTP header for the registry */ "cker-Endpoints:" @@ -108,9 +109,9 @@ struct DckImport { #define PAYLOAD_MAX (16*1024*1024) #define LAYERS_MAX 2048 -static int dck_import_name_add_job(DckImportName *name, DckImportJobType type, const char *url, DckImportJob **ret); +static int dkr_import_name_add_job(DkrImportName *name, DkrImportJobType type, const char *url, DkrImportJob **ret); -static DckImportJob *dck_import_job_unref(DckImportJob *job) { +static DkrImportJob *dkr_import_job_unref(DkrImportJob *job) { if (!job) return NULL; @@ -143,7 +144,7 @@ static DckImportJob *dck_import_job_unref(DckImportJob *job) { return NULL; } -static DckImportName *dck_import_name_unref(DckImportName *name) { +static DkrImportName *dkr_import_name_unref(DkrImportName *name) { if (!name) return NULL; @@ -162,6 +163,7 @@ static DckImportName *dck_import_name_unref(DckImportName *name) { if (name->job_layer) set_remove(name->job_layer->needed_by, name); + free(name->index_url); free(name->name); free(name->id); free(name->tag); @@ -173,10 +175,10 @@ static DckImportName *dck_import_name_unref(DckImportName *name) { return NULL; } -DEFINE_TRIVIAL_CLEANUP_FUNC(DckImportJob*, dck_import_job_unref); -DEFINE_TRIVIAL_CLEANUP_FUNC(DckImportName*, dck_import_name_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(DkrImportJob*, dkr_import_job_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(DkrImportName*, dkr_import_name_unref); -static void dck_import_finish(DckImport *import, int error) { +static void dkr_import_finish(DkrImport *import, int error) { assert(import); if (import->on_finished) @@ -218,7 +220,7 @@ static int parse_id(const void *payload, size_t size, char **ret) { if (t != JSON_END) return -EBADMSG; - if (!dck_id_is_valid(id)) + if (!dkr_id_is_valid(id)) return -EBADMSG; *ret = id; @@ -272,7 +274,7 @@ static int parse_ancestry(const void *payload, size_t size, char ***ret) { case STATE_ITEM: if (t == JSON_STRING) { - if (!dck_id_is_valid(str)) + if (!dkr_id_is_valid(str)) return -EBADMSG; if (n+1 > LAYERS_MAX) @@ -324,7 +326,7 @@ static int parse_ancestry(const void *payload, size_t size, char ***ret) { } } -static const char *dck_import_name_current_layer(DckImportName *name) { +static const char *dkr_import_name_current_layer(DkrImportName *name) { assert(name); if (strv_isempty(name->ancestry)) @@ -333,7 +335,7 @@ static const char *dck_import_name_current_layer(DckImportName *name) { return name->ancestry[name->current_ancestry]; } -static const char *dck_import_name_current_base_layer(DckImportName *name) { +static const char *dkr_import_name_current_base_layer(DkrImportName *name) { assert(name); if (strv_isempty(name->ancestry)) @@ -345,7 +347,7 @@ static const char *dck_import_name_current_base_layer(DckImportName *name) { return name->ancestry[name->current_ancestry-1]; } -static char** dck_import_name_get_registries(DckImportName *name) { +static char** dkr_import_name_get_registries(DkrImportName *name) { assert(name); if (!name->job_images) @@ -360,7 +362,7 @@ static char** dck_import_name_get_registries(DckImportName *name) { return name->job_images->response_registries; } -static const char*dck_import_name_get_token(DckImportName *name) { +static const char*dkr_import_name_get_token(DkrImportName *name) { assert(name); if (!name->job_images) @@ -372,7 +374,7 @@ static const char*dck_import_name_get_token(DckImportName *name) { return name->job_images->response_token; } -static void dck_import_name_maybe_finish(DckImportName *name) { +static void dkr_import_name_maybe_finish(DkrImportName *name) { int r; assert(name); @@ -389,7 +391,7 @@ static void dck_import_name_maybe_finish(DckImportName *name) { if (name->job_layer && !name->job_json->done) return; - if (dck_import_name_current_layer(name)) + if (dkr_import_name_current_layer(name)) return; if (name->local) { @@ -398,7 +400,7 @@ static void dck_import_name_maybe_finish(DckImportName *name) { assert(name->id); p = strappenda("/var/lib/container/", name->local); - q = strappenda("/var/lib/container/.dck-", name->id); + q = strappenda("/var/lib/container/.dkr-", name->id); if (name->force_local) { (void) btrfs_subvol_remove(p); @@ -408,17 +410,17 @@ static void dck_import_name_maybe_finish(DckImportName *name) { r = btrfs_subvol_snapshot(q, p, false, false); if (r < 0) { log_error_errno(r, "Failed to snapshot final image: %m"); - dck_import_finish(name->import, r); + dkr_import_finish(name->import, r); return; } log_info("Created new image %s.", p); } - dck_import_finish(name->import, 0); + dkr_import_finish(name->import, 0); } -static int dck_import_job_run_tar(DckImportJob *job) { +static int dkr_import_job_run_tar(DkrImportJob *job) { _cleanup_close_pair_ int pipefd[2] = { -1, -1 }; bool gzip; @@ -505,7 +507,7 @@ static int dck_import_job_run_tar(DckImportJob *job) { return 0; } -static int dck_import_name_pull_layer(DckImportName *name) { +static int dkr_import_name_pull_layer(DkrImportName *name) { _cleanup_free_ char *path = NULL, *temp = NULL; const char *url, *layer = NULL, *base = NULL; char **rg; @@ -519,13 +521,13 @@ static int dck_import_name_pull_layer(DckImportName *name) { } for (;;) { - layer = dck_import_name_current_layer(name); + layer = dkr_import_name_current_layer(name); if (!layer) { - dck_import_name_maybe_finish(name); + dkr_import_name_maybe_finish(name); return 0; } - path = strjoin("/var/lib/container/.dck-", layer, NULL); + path = strjoin("/var/lib/container/.dkr-", layer, NULL); if (!path) return log_oom(); @@ -544,11 +546,11 @@ static int dck_import_name_pull_layer(DckImportName *name) { path = NULL; } - rg = dck_import_name_get_registries(name); + rg = dkr_import_name_get_registries(name); assert(rg && rg[0]); url = strappenda(PROTOCOL_PREFIX, rg[0], "/v1/images/", layer, "/layer"); - r = dck_import_name_add_job(name, DCK_IMPORT_JOB_LAYER, url, &name->job_layer); + r = dkr_import_name_add_job(name, DKR_IMPORT_JOB_LAYER, url, &name->job_layer); if (r < 0) { log_error_errno(r, "Failed to issue HTTP request: %m"); return r; @@ -562,11 +564,11 @@ static int dck_import_name_pull_layer(DckImportName *name) { if (r < 0) return log_oom(); - base = dck_import_name_current_base_layer(name); + base = dkr_import_name_current_base_layer(name); if (base) { const char *base_path; - base_path = strappend("/var/lib/container/.dck-", base); + base_path = strappend("/var/lib/container/.dkr-", base); r = btrfs_subvol_snapshot(base_path, temp, false, true); } else r = btrfs_subvol_make(temp); @@ -581,7 +583,7 @@ static int dck_import_name_pull_layer(DckImportName *name) { return 0; } -static void dck_import_name_job_finished(DckImportName *name, DckImportJob *job) { +static void dkr_import_name_job_finished(DkrImportName *name, DkrImportJob *job) { int r; assert(name); @@ -596,7 +598,7 @@ static void dck_import_name_job_finished(DckImportName *name, DckImportJob *job) assert(!name->job_json); assert(!name->job_layer); - rg = dck_import_name_get_registries(name); + rg = dkr_import_name_get_registries(name); if (strv_isempty(rg)) { log_error("Didn't get registry information."); r = -EBADMSG; @@ -607,7 +609,7 @@ static void dck_import_name_job_finished(DckImportName *name, DckImportJob *job) url = strappenda(PROTOCOL_PREFIX, rg[0], "/v1/repositories/", name->name, "/tags/", name->tag); - r = dck_import_name_add_job(name, DCK_IMPORT_JOB_TAGS, url, &name->job_tags); + r = dkr_import_name_add_job(name, DKR_IMPORT_JOB_TAGS, url, &name->job_tags); if (r < 0) { log_error_errno(r, "Failed to issue HTTP request: %m"); goto fail; @@ -630,20 +632,20 @@ static void dck_import_name_job_finished(DckImportName *name, DckImportJob *job) free(name->id); name->id = id; - rg = dck_import_name_get_registries(name); + rg = dkr_import_name_get_registries(name); assert(rg && rg[0]); log_info("Tag lookup succeeded, resolved to layer %s.", name->id); url = strappenda(PROTOCOL_PREFIX, rg[0], "/v1/images/", name->id, "/ancestry"); - r = dck_import_name_add_job(name, DCK_IMPORT_JOB_ANCESTRY, url, &name->job_ancestry); + r = dkr_import_name_add_job(name, DKR_IMPORT_JOB_ANCESTRY, url, &name->job_ancestry); if (r < 0) { log_error_errno(r, "Failed to issue HTTP request: %m"); goto fail; } url = strappenda(PROTOCOL_PREFIX, rg[0], "/v1/images/", name->id, "/json"); - r = dck_import_name_add_job(name, DCK_IMPORT_JOB_JSON, url, &name->job_json); + r = dkr_import_name_add_job(name, DKR_IMPORT_JOB_JSON, url, &name->job_json); if (r < 0) { log_error_errno(r, "Failed to issue HTTP request: %m"); goto fail; @@ -674,18 +676,18 @@ static void dck_import_name_job_finished(DckImportName *name, DckImportJob *job) name->ancestry = ancestry; name->current_ancestry = 0; - r = dck_import_name_pull_layer(name); + r = dkr_import_name_pull_layer(name); if (r < 0) goto fail; } else if (name->job_json == job) { - dck_import_name_maybe_finish(name); + dkr_import_name_maybe_finish(name); } else if (name->job_layer == job) { name->current_ancestry ++; - r = dck_import_name_pull_layer(name); + r = dkr_import_name_pull_layer(name); if (r < 0) goto fail; @@ -695,13 +697,13 @@ static void dck_import_name_job_finished(DckImportName *name, DckImportJob *job) return; fail: - dck_import_finish(name->import, r); + dkr_import_finish(name->import, r); } -static void dck_import_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) { - DckImportJob *job = NULL; +static void dkr_import_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) { + DkrImportJob *job = NULL; CURLcode code; - DckImportName *n; + DkrImportName *n; long status; Iterator i; int r; @@ -737,7 +739,7 @@ static void dck_import_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result switch (job->type) { - case DCK_IMPORT_JOB_LAYER: { + case DKR_IMPORT_JOB_LAYER: { siginfo_t si; if (!job->tar_stream) { @@ -791,16 +793,16 @@ static void dck_import_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result } SET_FOREACH(n, job->needed_by, i) - dck_import_name_job_finished(n, job); + dkr_import_name_job_finished(n, job); return; fail: - dck_import_finish(job->import, r); + dkr_import_finish(job->import, r); } -static size_t dck_import_job_write_callback(void *contents, size_t size, size_t nmemb, void *userdata) { - DckImportJob *j = userdata; +static size_t dkr_import_job_write_callback(void *contents, size_t size, size_t nmemb, void *userdata) { + DkrImportJob *j = userdata; size_t sz = size * nmemb; char *p; int r; @@ -835,21 +837,21 @@ static size_t dck_import_job_write_callback(void *contents, size_t size, size_t j->payload_size += sz; j->payload = p; - r = dck_import_job_run_tar(j); + r = dkr_import_job_run_tar(j); if (r < 0) goto fail; return sz; fail: - dck_import_finish(j->import, r); + dkr_import_finish(j->import, r); return 0; } -static size_t dck_import_job_header_callback(void *contents, size_t size, size_t nmemb, void *userdata) { +static size_t dkr_import_job_header_callback(void *contents, size_t size, size_t nmemb, void *userdata) { _cleanup_free_ char *registry = NULL; size_t sz = size * nmemb; - DckImportJob *j = userdata; + DkrImportJob *j = userdata; char *token; int r; @@ -896,13 +898,13 @@ static size_t dck_import_job_header_callback(void *contents, size_t size, size_t return sz; fail: - dck_import_finish(j->import, r); + dkr_import_finish(j->import, r); return 0; } -static int dck_import_name_add_job(DckImportName *name, DckImportJobType type, const char *url, DckImportJob **ret) { - _cleanup_(dck_import_job_unrefp) DckImportJob *j = NULL; - DckImportJob *f = NULL; +static int dkr_import_name_add_job(DkrImportName *name, DkrImportJobType type, const char *url, DkrImportJob **ret) { + _cleanup_(dkr_import_job_unrefp) DkrImportJob *j = NULL; + DkrImportJob *f = NULL; const char *t, *token; int r; @@ -927,7 +929,7 @@ static int dck_import_name_add_job(DckImportName *name, DckImportJobType type, c if (r < 0) return r; - j = new0(DckImportJob, 1); + j = new0(DkrImportJob, 1); if (!j) return -ENOMEM; @@ -945,7 +947,7 @@ static int dck_import_name_add_job(DckImportName *name, DckImportJobType type, c if (r < 0) return r; - token = dck_import_name_get_token(name); + token = dkr_import_name_get_token(name); if (token) t = strappenda("Authorization: Token ", token); else @@ -958,13 +960,13 @@ static int dck_import_name_add_job(DckImportName *name, DckImportJobType type, c if (curl_easy_setopt(j->curl, CURLOPT_HTTPHEADER, j->request_header) != CURLE_OK) return -EIO; - if (curl_easy_setopt(j->curl, CURLOPT_WRITEFUNCTION, dck_import_job_write_callback) != CURLE_OK) + if (curl_easy_setopt(j->curl, CURLOPT_WRITEFUNCTION, dkr_import_job_write_callback) != CURLE_OK) return -EIO; if (curl_easy_setopt(j->curl, CURLOPT_WRITEDATA, j) != CURLE_OK) return -EIO; - if (curl_easy_setopt(j->curl, CURLOPT_HEADERFUNCTION, dck_import_job_header_callback) != CURLE_OK) + if (curl_easy_setopt(j->curl, CURLOPT_HEADERFUNCTION, dkr_import_job_header_callback) != CURLE_OK) return -EIO; if (curl_easy_setopt(j->curl, CURLOPT_HEADERDATA, j) != CURLE_OK) @@ -990,24 +992,24 @@ static int dck_import_name_add_job(DckImportName *name, DckImportJobType type, c return 1; } -static int dck_import_name_begin(DckImportName *name) { +static int dkr_import_name_begin(DkrImportName *name) { const char *url; assert(name); assert(!name->job_images); - url = strappenda(PROTOCOL_PREFIX, INDEX_HOST, "/v1/repositories/", name->name, "/images"); + url = strappenda(name->index_url, "/v1/repositories/", name->name, "/images"); - return dck_import_name_add_job(name, DCK_IMPORT_JOB_IMAGES, url, &name->job_images); + return dkr_import_name_add_job(name, DKR_IMPORT_JOB_IMAGES, url, &name->job_images); } -int dck_import_new(DckImport **import, sd_event *event, dck_import_on_finished on_finished, void *userdata) { - _cleanup_(dck_import_unrefp) DckImport *i = NULL; +int dkr_import_new(DkrImport **import, sd_event *event, dkr_import_on_finished on_finished, void *userdata) { + _cleanup_(dkr_import_unrefp) DkrImport *i = NULL; int r; assert(import); - i = new0(DckImport, 1); + i = new0(DkrImport, 1); if (!i) return -ENOMEM; @@ -1026,7 +1028,7 @@ int dck_import_new(DckImport **import, sd_event *event, dck_import_on_finished o if (r < 0) return r; - i->glue->on_finished = dck_import_curl_on_finished; + i->glue->on_finished = dkr_import_curl_on_finished; i->glue->userdata = i; *import = i; @@ -1035,30 +1037,31 @@ int dck_import_new(DckImport **import, sd_event *event, dck_import_on_finished o return 0; } -DckImport* dck_import_unref(DckImport *import) { - DckImportName *n; - DckImportJob *j; +DkrImport* dkr_import_unref(DkrImport *import) { + DkrImportName *n; + DkrImportJob *j; if (!import) return NULL; while ((n = hashmap_steal_first(import->names))) - dck_import_name_unref(n); + dkr_import_name_unref(n); hashmap_free(import->names); while ((j = hashmap_steal_first(import->jobs))) - dck_import_job_unref(j); + dkr_import_job_unref(j); hashmap_free(import->jobs); curl_glue_unref(import->glue); sd_event_unref(import->event); free(import); + return NULL; } -int dck_import_cancel(DckImport *import, const char *name) { - DckImportName *n; +int dkr_import_cancel(DkrImport *import, const char *name) { + DkrImportName *n; assert(import); assert(name); @@ -1067,17 +1070,19 @@ int dck_import_cancel(DckImport *import, const char *name) { if (!n) return 0; - dck_import_name_unref(n); + dkr_import_name_unref(n); return 1; } -int dck_import_pull(DckImport *import, const char *name, const char *tag, const char *local, bool force_local) { - _cleanup_(dck_import_name_unrefp) DckImportName *n = NULL; +int dkr_import_pull(DkrImport *import, const char *index_url, const char *name, const char *tag, const char *local, bool force_local) { + _cleanup_(dkr_import_name_unrefp) DkrImportName *n = NULL; + char *e; int r; assert(import); - assert(dck_name_is_valid(name)); - assert(dck_tag_is_valid(tag)); + assert(dkr_url_is_valid(index_url)); + assert(dkr_name_is_valid(name)); + assert(dkr_tag_is_valid(tag)); assert(!local || machine_name_is_valid(local)); if (hashmap_get(import->names, name)) @@ -1087,12 +1092,19 @@ int dck_import_pull(DckImport *import, const char *name, const char *tag, const if (r < 0) return r; - n = new0(DckImportName, 1); + n = new0(DkrImportName, 1); if (!n) return -ENOMEM; n->import = import; + n->index_url = strdup(index_url); + if (!n->index_url) + return -ENOMEM; + e = endswith(n->index_url, "/"); + if (e) + *e = NULL; + n->name = strdup(name); if (!n->name) return -ENOMEM; @@ -1112,9 +1124,9 @@ int dck_import_pull(DckImport *import, const char *name, const char *tag, const if (r < 0) return r; - r = dck_import_name_begin(n); + r = dkr_import_name_begin(n); if (r < 0) { - dck_import_cancel(import, n->name); + dkr_import_cancel(import, n->name); n = NULL; return r; } @@ -1124,7 +1136,7 @@ int dck_import_pull(DckImport *import, const char *name, const char *tag, const return 0; } -bool dck_name_is_valid(const char *name) { +bool dkr_name_is_valid(const char *name) { const char *slash, *p; if (isempty(name)) @@ -1144,7 +1156,7 @@ bool dck_name_is_valid(const char *name) { return true; } -bool dck_id_is_valid(const char *id) { +bool dkr_id_is_valid(const char *id) { if (!filename_is_valid(id)) return false; @@ -1154,3 +1166,12 @@ bool dck_id_is_valid(const char *id) { return true; } + +bool dkr_url_is_valid(const char *url) { + + if (!startswith(url, "http://") && + !startswith(url, "https://")) + return false; + + return ascii_is_valid(url); +} diff --git a/src/import/import-dck.h b/src/import/import-dkr.h similarity index 58% rename from src/import/import-dck.h rename to src/import/import-dkr.h index cd2d27c7ee..a95169590b 100644 --- a/src/import/import-dck.h +++ b/src/import/import-dkr.h @@ -22,18 +22,19 @@ #include "sd-event.h" #include "util.h" -typedef struct DckImport DckImport; +typedef struct DkrImport DkrImport; -typedef void (*dck_import_on_finished)(DckImport *import, int error, void *userdata); +typedef void (*dkr_import_on_finished)(DkrImport *import, int error, void *userdata); -int dck_import_new(DckImport **import, sd_event *event, dck_import_on_finished on_finished, void *userdata); -DckImport* dck_import_unref(DckImport *import); +int dkr_import_new(DkrImport **import, sd_event *event, dkr_import_on_finished on_finished, void *userdata); +DkrImport* dkr_import_unref(DkrImport *import); -DEFINE_TRIVIAL_CLEANUP_FUNC(DckImport*, dck_import_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(DkrImport*, dkr_import_unref); -int dck_import_pull(DckImport *import, const char *name, const char *tag, const char *local, bool force_local); -int dck_import_cancel(DckImport *import, const char *name); +int dkr_import_pull(DkrImport *import, const char *index_url, const char *name, const char *tag, const char *local, bool force_local); +int dkr_import_cancel(DkrImport *import, const char *name); -bool dck_name_is_valid(const char *name); -bool dck_id_is_valid(const char *id); -#define dck_tag_is_valid(tag) filename_is_valid(tag) +bool dkr_name_is_valid(const char *name); +bool dkr_id_is_valid(const char *id); +#define dkr_tag_is_valid(tag) filename_is_valid(tag) +bool dkr_url_is_valid(const char *url); diff --git a/src/import/import.c b/src/import/import.c index 6fd3eeb2bc..11d2e05f09 100644 --- a/src/import/import.c +++ b/src/import/import.c @@ -25,11 +25,13 @@ #include "event-util.h" #include "verbs.h" #include "build.h" -#include "import-dck.h" +#include "import-dkr.h" static bool arg_force = false; -static void on_finished(DckImport *import, int error, void *userdata) { +static const char* arg_dkr_index_url = DEFAULT_DKR_INDEX_URL; + +static void on_finished(DkrImport *import, int error, void *userdata) { sd_event *event = userdata; assert(import); @@ -41,12 +43,17 @@ static void on_finished(DckImport *import, int error, void *userdata) { sd_event_exit(event, error); } -static int pull_dck(int argc, char *argv[], void *userdata) { - _cleanup_(dck_import_unrefp) DckImport *import = NULL; +static int pull_dkr(int argc, char *argv[], void *userdata) { + _cleanup_(dkr_import_unrefp) DkrImport *import = NULL; _cleanup_event_unref_ sd_event *event = NULL; const char *name, *tag, *local; int r; + if (!arg_dkr_index_url) { + log_error("Please specify an index URL with --dkr-index-url="); + return -EINVAL; + } + tag = strchr(argv[1], ':'); if (tag) { name = strndupa(argv[1], tag - argv[1]); @@ -69,12 +76,12 @@ static int pull_dck(int argc, char *argv[], void *userdata) { if (streq(local, "-") || isempty(local)) local = NULL; - if (!dck_name_is_valid(name)) { + if (!dkr_name_is_valid(name)) { log_error("Remote name '%s' is not valid.", name); return -EINVAL; } - if (!dck_tag_is_valid(tag)) { + if (!dkr_tag_is_valid(tag)) { log_error("Tag name '%s' is not valid.", tag); return -EINVAL; } @@ -108,11 +115,11 @@ static int pull_dck(int argc, char *argv[], void *userdata) { sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); - r = dck_import_new(&import, event, on_finished, event); + r = dkr_import_new(&import, event, on_finished, event); if (r < 0) return log_error_errno(r, "Failed to allocate importer: %m"); - r = dck_import_pull(import, name, tag, local, arg_force); + r = dkr_import_pull(import, arg_dkr_index_url, name, tag, local, arg_force); if (r < 0) return log_error_errno(r, "Failed to pull image: %m"); @@ -131,9 +138,10 @@ static int help(int argc, char *argv[], void *userdata) { "Import container or virtual machine image.\n\n" " -h --help Show this help\n" " --version Show package version\n" - " --force Force creation of image\n\n" + " --force Force creation of image\n" + " --dkr-index-url=URL Specify index URL to use for downloads\n\n" "Commands:\n" - " pull-dck REMOTE [NAME] Download an image\n", + " pull-dkr REMOTE [NAME] Download an image\n", program_invocation_short_name); return 0; @@ -144,12 +152,14 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_FORCE, + ARG_DKR_INDEX_URL, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "force", no_argument, NULL, ARG_FORCE }, + { "dkr-index-url", required_argument, NULL, ARG_DKR_INDEX_URL }, {} }; @@ -174,6 +184,15 @@ static int parse_argv(int argc, char *argv[]) { arg_force = true; break; + case ARG_DKR_INDEX_URL: + if (!dkr_url_is_valid(optarg)) { + log_error("Index URL is not valid: %s", optarg); + return -EINVAL; + } + + arg_dkr_index_url = optarg; + break; + case '?': return -EINVAL; @@ -188,7 +207,7 @@ static int import_main(int argc, char *argv[]) { static const Verb verbs[] = { { "help", VERB_ANY, VERB_ANY, 0, help }, - { "pull-dck", 2, 3, 0, pull_dck }, + { "pull-dkr", 2, 3, 0, pull_dkr }, {} };