Skip to content

Commit ff829cb

Browse files
authored
Merge pull request #2654 from DeusData/fix/image-unknown-registry
fix(docker): never invent a registry host for an image
2 parents cfcf752 + e99c159 commit ff829cb

6 files changed

Lines changed: 209 additions & 70 deletions

File tree

‎src/pipeline/pass_docker.c‎

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
* ENV); a reference without a value leaves the image unknown, and an unknown
1212
* image is no edge.
1313
*
14-
* Image identity is the normalised repository: docker.io for an image
15-
* without a registry host, library/ for an official one-segment image;
16-
* tag and digest stay on the edge.
14+
* Image identity is the repository as written, tag and digest dropped (they
15+
* stay on the edge). Its registry is the host the reference names -- Docker
16+
* Hub's spellings as docker.io, with library/ for an official one-segment
17+
* image -- else "unknown": no host is invented for a reference naming none.
1718
*
1819
* PHASE 4 P4.1b: what the container runs. The last stage's ENTRYPOINT (else
1920
* CMD) SPAWNS -- from the Dockerfile's Module {api:dockerfile}:
@@ -268,7 +269,6 @@ static const char *dk_expand(dk_t *d, const dk_var_t *vars, const char *text) {
268269
return out;
269270
}
270271

271-
/* The repository identity of image reference `ref` into out. */
272272
/* Only characters an image reference can hold (name, :tag, @digest) -- a
273273
* template's placeholder (`<.Values.image>`, `<tpl>`) or an expression is
274274
* no image. */
@@ -281,7 +281,15 @@ static bool dk_ref_chars(const char *ref) {
281281
return ref[0] != '\0';
282282
}
283283

284-
static bool dk_normalize(const char *ref, char *out, size_t sz) {
284+
/* The registry of a reference that names no host. */
285+
static const char DK_REGISTRY_UNKNOWN[] = "unknown";
286+
287+
/* The repository identity of image reference `ref` into out, the registry
288+
* its host names into reg. A reference without a host is the repository as
289+
* written, its registry unknown: docker.io is only Docker's default -- a
290+
* short-name search list (Podman, CRI-O) or a local-only build tag resolves
291+
* elsewhere or nowhere. */
292+
static bool dk_normalize(const char *ref, char *out, size_t sz, char *reg, size_t reg_sz) {
285293
if (!dk_ref_chars(ref)) {
286294
return false;
287295
}
@@ -300,15 +308,12 @@ static bool dk_normalize(const char *ref, char *out, size_t sz) {
300308
return false;
301309
}
302310
char *first_end = strchr(r, '/');
303-
if (!first_end) {
304-
snprintf(out, sz, "docker.io/library/%s", r);
305-
return true;
306-
}
307-
size_t fl = (size_t)(first_end - r);
308-
bool host = memchr(r, '.', fl) || memchr(r, ':', fl) ||
309-
(fl == strlen("localhost") && strncmp(r, "localhost", fl) == 0);
311+
size_t fl = first_end ? (size_t)(first_end - r) : 0;
312+
bool host = first_end && (memchr(r, '.', fl) || memchr(r, ':', fl) ||
313+
(fl == strlen("localhost") && strncmp(r, "localhost", fl) == 0));
310314
if (!host) {
311-
snprintf(out, sz, "docker.io/%s", r);
315+
snprintf(out, sz, "%s", r);
316+
snprintf(reg, reg_sz, "%s", DK_REGISTRY_UNKNOWN);
312317
return true;
313318
}
314319
const char *rest = first_end + SKIP_ONE;
@@ -318,8 +323,10 @@ static bool dk_normalize(const char *ref, char *out, size_t sz) {
318323
(fl == strlen("registry-1.docker.io") && strncmp(r, "registry-1.docker.io", fl) == 0);
319324
if (hub) {
320325
snprintf(out, sz, "docker.io/%s%s", strchr(rest, '/') ? "" : "library/", rest);
326+
snprintf(reg, reg_sz, "docker.io");
321327
} else {
322328
snprintf(out, sz, "%.*s/%s", (int)fl, r, rest);
329+
snprintf(reg, reg_sz, "%.*s", (int)fl, r);
323330
}
324331
return true;
325332
}
@@ -365,15 +372,20 @@ static int dk_stage_of(const dk_t *d, const char *ref) {
365372

366373
int64_t cbm_pipeline_image_node(cbm_pipeline_ctx_t *ctx, const char *ref) {
367374
char repo[CBM_SZ_512];
368-
if (!ref || dk_ieq(ref, "scratch") || !dk_normalize(ref, repo, sizeof(repo))) {
375+
char reg[CBM_SZ_512];
376+
if (!ref || dk_ieq(ref, "scratch") ||
377+
!dk_normalize(ref, repo, sizeof(repo), reg, sizeof(reg))) {
369378
return 0;
370379
}
371380
char qn[CBM_SZ_1K];
372381
snprintf(qn, sizeof(qn), "__image__%s", repo);
373382
char esc_repo[CBM_SZ_1K];
383+
char esc_reg[CBM_SZ_1K];
374384
cbm_json_escape(esc_repo, (int)sizeof(esc_repo), repo);
385+
cbm_json_escape(esc_reg, (int)sizeof(esc_reg), reg);
375386
char node_props[CBM_SZ_2K];
376-
snprintf(node_props, sizeof(node_props), "{\"repository\":\"%s\"}", esc_repo);
387+
snprintf(node_props, sizeof(node_props), "{\"repository\":\"%s\",\"registry\":\"%s\"}",
388+
esc_repo, esc_reg);
377389
return cbm_gbuf_upsert_node(ctx->gbuf, "Image", repo, qn, "", 0, 0, node_props);
378390
}
379391

@@ -2054,7 +2066,7 @@ static int dk_hub_match(const char *tag, const char *const *comps, int nc) {
20542066
}
20552067

20562068
/* The Image of a component: `<repo>:<pattern>` (`*-frontend`: the
2057-
* prefix's version masked) {repository, component, tag_pattern}. */
2069+
* prefix's version masked) {repository, registry, component, tag_pattern}. */
20582070
static int64_t dk_hub_image(cbm_pipeline_ctx_t *ctx, const char *repo, const char *comp,
20592071
char pre_sep, char suf_sep) {
20602072
char head[PAIR_LEN + SKIP_ONE] = {0};
@@ -2073,16 +2085,24 @@ static int64_t dk_hub_image(cbm_pipeline_ctx_t *ctx, const char *repo, const cha
20732085
snprintf(pattern, sizeof(pattern), "%s%s%s", head, comp, tail);
20742086
snprintf(name, sizeof(name), "%s:%s", repo, pattern);
20752087
snprintf(qn, sizeof(qn), "__image__%s", name);
2088+
char same[CBM_SZ_1K];
2089+
char reg[CBM_SZ_512];
2090+
if (!dk_normalize(repo, same, sizeof(same), reg, sizeof(reg))) {
2091+
snprintf(reg, sizeof(reg), "%s", DK_REGISTRY_UNKNOWN);
2092+
}
20762093
char esc_r[CBM_SZ_1K];
2094+
char esc_g[CBM_SZ_1K];
20772095
char esc_c[CBM_SZ_1K];
20782096
char esc_p[CBM_SZ_1K];
20792097
cbm_json_escape(esc_r, (int)sizeof(esc_r), repo);
2098+
cbm_json_escape(esc_g, (int)sizeof(esc_g), reg);
20802099
cbm_json_escape(esc_c, (int)sizeof(esc_c), comp);
20812100
cbm_json_escape(esc_p, (int)sizeof(esc_p), pattern);
20822101
char props[CBM_SZ_4K];
20832102
snprintf(props, sizeof(props),
2084-
"{\"repository\":\"%s\",\"component\":\"%s\",\"tag_pattern\":\"%s\"}", esc_r, esc_c,
2085-
esc_p);
2103+
"{\"repository\":\"%s\",\"registry\":\"%s\",\"component\":\"%s\","
2104+
"\"tag_pattern\":\"%s\"}",
2105+
esc_r, esc_g, esc_c, esc_p);
20862106
return cbm_gbuf_upsert_node(ctx->gbuf, "Image", name, qn, "", 0, 0, props);
20872107
}
20882108

‎src/pipeline/pipeline_internal.h‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,9 +1332,10 @@ bool cbm_ansible_is_sequence(const char *src);
13321332
* (pass_terraform.c). */
13331333
bool cbm_repo_rel_join(const char *dir, const char *v, char *out, size_t sz);
13341334

1335-
/* The Image node of image reference `ref` (its normalised repository:
1336-
* docker.io for no registry host, library/ for an official image; tag and
1337-
* digest dropped), made when new; 0 for scratch or no image. */
1335+
/* The Image node of image reference `ref` (its repository as written, tag
1336+
* and digest dropped; Docker Hub's host spellings as docker.io with library/
1337+
* for an official image; registry "unknown" when the reference names no
1338+
* host -- none is invented), made when new; 0 for scratch or no image. */
13381339
int64_t cbm_pipeline_image_node(cbm_pipeline_ctx_t *ctx, const char *ref);
13391340

13401341
/* A chart repository URL as an identity (pass_k8s.c): `url` trimmed, its

‎src/store/store.h‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@ typedef struct cbm_store_read_scope cbm_store_read_scope_t;
2929
* 1 #1108: File-node QNs keep the file extension.
3030
* 2 Kubernetes objects: one Resource per YAML document, QN
3131
* <file>::<group>/<Kind>/<declared namespace or ->/<name>; a
32-
* Dockerfile.<variant> keeps its suffix in its QNs. */
33-
#define CBM_INDEX_FORMAT_VERSION 2
32+
* Dockerfile.<variant> keeps its suffix in its QNs.
33+
* 3 Image identity invents no registry: a reference without a host is
34+
* __image__<repository as written>, registry "unknown" -- no longer
35+
* __image__docker.io/[library/]<repository>. */
36+
#define CBM_INDEX_FORMAT_VERSION 3
3437
#define CBM_STORE_CANCELLED (-3)
3538
#define CBM_STORE_SCAN_LIMIT (-4)
3639
#define CBM_STORE_CALLBACK_ERR (-5)

0 commit comments

Comments
 (0)