Skip to content

Conversation

Fricounet
Copy link
Contributor

This attempts to solve both dragonflyoss/nydus#1691 and dragonflyoss/nydus#1692.

Attempting to push some ECR manifests has 2 issues currently:

  • with-referrer fails because the subject field in the manifest has a platform field. Although this is ok from an OCI spec perspective, ECR doesn't support it and it is not really needed so we can remove it
  • platform fails when attempting to build multi-arch manifests because the os.feature field in the manifest is not supported either. We can remove it because this is not really supported yet in any container runtime. However, we still keep it when building images through merge-platform as it is the only way to differentiate a regular OCI image from a nydus one in that case. Fortunately, the merge-platform code goes through a different code path that uses Harbor's acceleration service and the os.feature field is set there.

I did test this by rebuilding nydusify using the fixed converter and tried to push both images to ECR, which worked.
Additionally, I made sure that the merge-platform field was still working:

./cmd/nydusify convert --source foo:bar --target-suffix -nydus-platform --merge-platform --platform "linux/amd64,linux/arm64"
INFO[2025-05-21T18:32:49+02:00] pulling image foo:bar  module=converter
INFO[2025-05-21T18:32:56+02:00] pulled image foo:bar , elapse 7.645556534s  module=converter
INFO[2025-05-21T18:32:56+02:00] converting image foo:bar  module=converter
INFO[2025-05-21T18:32:59+02:00] converted image foo:bar-nydus-platform , elapse 2.528599639s  module=converter
INFO[2025-05-21T18:32:59+02:00] pushing image foo:bar-nydus-platform  module=converter
INFO[2025-05-21T18:33:03+02:00] pushed image foo:bar-nydus-platform, elapse 4.147958056s  module=converter


crane manifest foo:bar-nydus-platform | jq
{
  "schemaVersion": 2,
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:d794231637e1cb6b40d30712718b82e47a306350295bc349dc38ac96fe0c6958",
      "size": 721,
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:821c0238e5f7d2f95d90b897872f4584e56c9d89fd582c7eb2562583164768dd",
      "size": 721,
      "platform": {
        "architecture": "arm64",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:8b32e06f97f9c3423b0eea97b18946d11ca3a1fc86df5ce1339c4634465b2d05",
      "size": 1588,
      "platform": {
        "architecture": "amd64",
        "os": "linux",
        "os.features": [
          "nydus.remoteimage.v1"
        ]
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:8c087d44e299989ea4a68329141bfb771883b4442ce1997ed5794e8936c258ef",
      "size": 1588,
      "platform": {
        "architecture": "arm64",
        "os": "linux",
        "os.features": [
          "nydus.remoteimage.v1"
        ]
      }
    }
  ]
}

Fricounet added 2 commits May 21, 2025 18:11
This field is not supported by certain registries like ECR and is not really needed according to dragonflyoss/nydus#1691.
This field is causing issues when attempting to push multi-arch images to ECR because the feature field is not supported in index manifests. According to dragonflyoss/nydus#1692, the goal of this feature is to help the container runtime pick the nydus image in an index manifest if there are multiple entries for the same architecture. However, as this is a feature that is not supported in any container runtime yet and the only way to get a manifest with both architecture is to use `nydusify convert --merge-platform`, which uses harbor acceleration-service to add the feature in the manifest, this means that we can remove it from the converter.
@Fricounet
Copy link
Contributor Author

If the PR is merged, a new release will have to be cut for the snapshotter in order to use it in nydusify right?

Copy link

codecov bot commented May 21, 2025

Codecov Report

Attention: Patch coverage is 0% with 6 lines in your changes missing coverage. Please review.

Project coverage is 21.39%. Comparing base (314951f) to head (6542a89).
Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
pkg/converter/convert_unix.go 0.00% 6 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #639      +/-   ##
==========================================
+ Coverage   21.36%   21.39%   +0.02%     
==========================================
  Files         122      122              
  Lines       13632    13614      -18     
==========================================
  Hits         2913     2913              
+ Misses      10398    10380      -18     
  Partials      321      321              
Files with missing lines Coverage Δ
pkg/converter/convert_unix.go 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

// Skip the manifest which is not modified.
continue
}
manifest.Platform.OSFeatures = append(manifest.Platform.OSFeatures, ManifestOSFeatureNydus)
Copy link

Choose a reason for hiding this comment

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

Why is it not sufficient to remove only the line manifest.Platform.OSFeatures = append(manifest.Platform.OSFeatures, ManifestOSFeatureNydus) ? I'm concerned that omitting index.Manifests[i] = manifest might introduce unexpected issues elsewhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@BraveY just removing the line you mentioned would indeed work. I removed the whole block because functionally, it now becomes:

for i, manifest := range index.Manifests {
  index.Manifests[i] = manifest
}

which, in my opinion does not serve much purpose 😅 except complicating the code. If you really prefer that we keep it, I can add it back if you want. What do you prefer?

Copy link

Choose a reason for hiding this comment

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

@BraveY just removing the line you mentioned would indeed work. I removed the whole block because functionally, it now becomes:

for i, manifest := range index.Manifests {
  index.Manifests[i] = manifest
}

which, in my opinion does not serve much purpose 😅 except complicating the code. If you really prefer that we keep it, I can add it back if you want. What do you prefer?

Appreciate the clarification! My mistake stemmed from assuming index was empty, but since readJSON already initializes it, the loop adds no value. Agreed—let’s remove the redundant code.

@BraveY
Copy link

BraveY commented May 22, 2025

If the PR is merged, a new release will have to be cut for the snapshotter in order to use it in nydusify right?

Once the PR is merged, a new release of the snapshotter will indeed need to be published to use it in nydusify. For testing purposes, you can temporarily pin the commit hash directly in go.mod instead of referencing a tag.

@BraveY
Copy link

BraveY commented May 23, 2025

If the PR is merged, a new release will have to be cut for the snapshotter in order to use it in nydusify right?

Once the PR is merged, a new release of the snapshotter will indeed need to be published to use it in nydusify. For testing purposes, you can temporarily pin the commit hash directly in go.mod instead of referencing a tag.

For testing purposes, let’s proceed with pinning the snapshotter’s commit hash in go.mod (using replace directive) to validate the proposed changes in nydusify.
Once the tests pass and there are no further updates to this PR, we can proceed with merging it. Does this plan work for you?

@@ -922,36 +922,18 @@ func ConvertHookFunc(opt MergeOption) converter.ConvertHookFunc {
}
}

// convertIndex modifies the original index by appending "nydus.remoteimage.v1"
// to the Platform.OSFeatures of each modified manifest descriptors.
// convertIndex modifies the original index converting it to manifest directly if it contains only one manifest.
func convertIndex(ctx context.Context, cs content.Store, orgDesc ocispec.Descriptor, newDesc *ocispec.Descriptor) (*ocispec.Descriptor, error) {
var orgIndex ocispec.Index
Copy link
Collaborator

@imeoer imeoer May 23, 2025

Choose a reason for hiding this comment

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

It seems we can remove the useless codes, also for the // Update image index in content store. below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Very good point, I hadn't caught that. Fixed in 6542a89

This code is useless now since we return the first manifest in the index directly without updating the index itself
@Fricounet
Copy link
Contributor Author

For testing purposes, let’s proceed with pinning the snapshotter’s commit hash in go.mod (using replace directive) to validate the proposed changes in nydusify.
Once the tests pass and there are no further updates to this PR, we can proceed with merging it. Does this plan work for you?

Sure, I'm currently struggling in go version incompatibility in the go mod of nydusify (which is also present on the latest release of the snapshotter), but I'll try to get this done asap

Copy link
Collaborator

@imeoer imeoer left a comment

Choose a reason for hiding this comment

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

Thanks, LGTM!

@imeoer
Copy link
Collaborator

imeoer commented May 26, 2025

Let's tag the next release as v0.15.2.

@imeoer imeoer merged commit 00c3cbe into containerd:main May 26, 2025
14 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants