Merge pull request #27153 from rhatdan/cursor

Add --replace option to podman artifact add command
This commit is contained in:
openshift-merge-bot[bot]
2025-10-07 17:09:03 +00:00
committed by GitHub
14 changed files with 345 additions and 14 deletions

View File

@ -43,6 +43,65 @@ class ArtifactTestCase(APITestCase):
# Assert blob media type fallback detection is working
self.assertEqual(artifact_layer["mediaType"], "application/octet-stream")
def test_add_with_replace(self):
ARTIFACT_NAME = "quay.io/myimage/newartifact:latest"
# Create first artifact
file1 = ArtifactFile()
parameters1: dict[str, str | list[str]] = {
"name": ARTIFACT_NAME,
"fileName": file1.name,
}
artifact1 = Artifact(self.uri(""), ARTIFACT_NAME, parameters1, file1)
add_response1 = artifact1.add()
self.assertEqual(add_response1.status_code, 201, add_response1.text)
original_digest = add_response1.json()["ArtifactDigest"]
# Create replacement artifact with replace=true
file2 = ArtifactFile()
parameters2: dict[str, str | list[str]] = {
"name": ARTIFACT_NAME,
"fileName": file2.name,
"replace": "true",
}
artifact2 = Artifact(self.uri(""), ARTIFACT_NAME, parameters2, file2)
add_response2 = artifact2.add()
self.assertEqual(add_response2.status_code, 201, add_response2.text)
new_digest = add_response2.json()["ArtifactDigest"]
# Verify artifacts were replaced (different digests)
self.assertNotEqual(original_digest, new_digest)
# Verify artifact exists and has the new content
inspect_response = artifact2.do_artifact_inspect_request()
self.assertEqual(inspect_response.status_code, 200)
inspect_json = inspect_response.json()
artifact_layer = inspect_json["Manifest"]["layers"][0]
# Should have only one layer (replaced, not appended)
self.assertEqual(len(inspect_json["Manifest"]["layers"]), 1)
# Verify it's the second file's content
self.assertEqual(artifact_layer["size"], file2.size)
self.assertEqual(
artifact_layer["annotations"]["org.opencontainers.image.title"], file2.name
)
url = self.uri("/artifacts/" + ARTIFACT_NAME)
r = requests.delete(url)
rjson = r.json()
# Assert correct response code
self.assertEqual(r.status_code, 200, r.text)
# Assert return response is json and contains digest
self.assertIn("sha256:", rjson["ArtifactDigests"][0])
def test_add_with_append(self):
ARTIFACT_NAME = "quay.io/myimage/myartifact:latest"
file = ArtifactFile(name="test_file_2")

View File

@ -0,0 +1,113 @@
#!/usr/bin/env bats -*- bats -*-
#
# Tests for podman artifact functionality
#
load helpers
function setup() {
basic_setup
}
function teardown() {
basic_teardown
}
# Helper function to create a test artifact file
create_test_file() {
local size=${1:-1024}
local filename=$(mktemp --tmpdir="${PODMAN_TMPDIR}" artifactfile.XXXXXX)
dd if=/dev/urandom of="$filename" bs=1 count="$size" 2>/dev/null
echo "$filename"
}
# bats test_tags=ci:parallel
@test "podman artifact add --replace basic functionality" {
local artifact_name="localhost/test/replace-artifact"
local file1 file2
file1=$(create_test_file 1024)
file2=$(create_test_file 2048)
# Add initial artifact
run_podman artifact add "$artifact_name" "$file1"
local first_digest="$output"
# Verify initial artifact exists
run_podman artifact inspect "$artifact_name"
# Replace with different file
run_podman artifact add --replace "$artifact_name" "$file2"
local second_digest="$output"
# Verify artifact was replaced (different digest)
assert "$first_digest" != "$second_digest" "Replace should create different digest"
# Verify artifact still exists and is accessible
run_podman artifact inspect "$artifact_name"
# Cleanup
run_podman artifact rm "$artifact_name"
rm -f "$file1" "$file2"
}
# bats test_tags=ci:parallel
@test "podman artifact add --replace nonexistent artifact" {
local artifact_name="localhost/test/nonexistent-artifact"
local file1
file1=$(create_test_file 1024)
# Using --replace on nonexistent artifact should succeed
run_podman artifact add --replace "$artifact_name" "$file1"
# Verify artifact was created
run_podman artifact inspect "$artifact_name"
# Cleanup
run_podman artifact rm "$artifact_name"
rm -f "$file1"
}
# bats test_tags=ci:parallel
@test "podman artifact add --replace and --append conflict" {
local artifact_name="localhost/test/conflict-artifact"
local file1
file1=$(create_test_file 1024)
# Using --replace and --append together should fail
run_podman 125 artifact add --replace --append "$artifact_name" "$file1"
assert "$output" =~ "--append and --replace options cannot be used together"
rm -f "$file1"
}
# bats test_tags=ci:parallel
@test "podman artifact add --replace with existing artifact" {
local artifact_name="localhost/test/existing-artifact"
local file1 file2
file1=$(create_test_file 512)
file2=$(create_test_file 1024)
# Create initial artifact
run_podman artifact add "$artifact_name" "$file1"
# Verify initial artifact exists
run_podman artifact inspect "$artifact_name"
# Adding same name without --replace should fail
run_podman 125 artifact add "$artifact_name" "$file2"
assert "$output" =~ "artifact already exists"
# Replace should succeed
run_podman artifact add --replace "$artifact_name" "$file2"
# Verify artifact was replaced
run_podman artifact inspect "$artifact_name"
# Cleanup
run_podman artifact rm "$artifact_name"
rm -f "$file1" "$file2"
}

View File

@ -0,0 +1,107 @@
#!/usr/bin/env bats -*- bats -*-
#
# Tests for podman artifact created date functionality
#
load helpers
# Create temporary artifact file for testing
function create_test_file() {
local content="$1"
local filename=$(random_string 12)
local filepath="$PODMAN_TMPDIR/$filename.txt"
echo "$content" > "$filepath"
echo "$filepath"
}
function setup() {
basic_setup
skip_if_remote "artifacts are not remote"
}
function teardown() {
run_podman artifact rm --all --ignore || true
basic_teardown
}
@test "podman artifact inspect shows created date in RFC3339" {
local content="test content for created date"
local testfile=$(create_test_file "$content")
local artifact_name="localhost/test/created-test"
# Record time before creation (in seconds for comparison)
local before_epoch=$(date +%s)
# Create artifact
run_podman artifact add $artifact_name "$testfile"
# Record time after creation (in seconds for comparison)
local after_epoch=$(date +%s)
# Inspect the artifact
run_podman artifact inspect $artifact_name
local output="$output"
# Parse the JSON output to get the created annotation
local created_annotation
created_annotation=$(echo "$output" | jq -r '.Manifest.annotations["org.opencontainers.image.created"]')
# Verify created annotation exists and is not null
assert "$created_annotation" != "null" "Should have org.opencontainers.image.created annotation"
assert "$created_annotation" != "" "Created annotation should not be empty"
# Verify it's a valid RFC3339 timestamp by trying to parse it
# Convert to epoch for comparison
local created_epoch
created_epoch=$(date -d "$created_annotation" +%s 2>/dev/null)
# Verify parsing succeeded
assert "$?" -eq 0 "Created timestamp should be valid RFC3339 format"
# Verify timestamp is within reasonable bounds
assert "$created_epoch" -ge "$before_epoch" "Created time should be after before_epoch"
assert "$created_epoch" -le "$after_epoch" "Created time should be before after_epoch"
# Clean up
rm -f "$testfile"
}
@test "podman artifact append preserves original created date" {
local content1="initial content"
local content2="appended content"
local testfile1=$(create_test_file "$content1")
local testfile2=$(create_test_file "$content2")
local artifact_name="localhost/test/append-test"
# Create initial artifact
run_podman artifact add $artifact_name "$testfile1"
# Get the original created timestamp
run_podman artifact inspect $artifact_name
local original_created
original_created=$(echo "$output" | jq -r '.Manifest.annotations["org.opencontainers.image.created"]')
# Wait a bit to ensure timestamps would differ if created new
sleep 1
# Append to artifact
run_podman artifact add --append $artifact_name "$testfile2"
# Get the created timestamp after append
run_podman artifact inspect $artifact_name
local current_created
current_created=$(echo "$output" | jq -r '.Manifest.annotations["org.opencontainers.image.created"]')
# Verify the created timestamp is preserved
assert "$current_created" = "$original_created" "Created timestamp should be preserved during append"
# Verify we have 2 layers now
local layer_count
layer_count=$(echo "$output" | jq '.Manifest.layers | length')
assert "$layer_count" -eq 2 "Should have 2 layers after append"
# Clean up
rm -f "$testfile1" "$testfile2"
}
# vim: filetype=sh