Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Docker engine #914

Draft
wants to merge 29 commits into
base: master
Choose a base branch
from
Draft

Add support for Docker engine #914

wants to merge 29 commits into from

Conversation

ezekg
Copy link
Member

@ezekg ezekg commented Nov 8, 2024

Closes #911. In the end, it should be as simple as docker save keygen/api:1.0.0 > keygen-1.0.0.tar and keygen upload keygen-1.0.0.tar — the rest should be automatically handled by the Docker engine.

Like with npm and friends, docker push will not be supported right away.

Prereqs

  • Implement the Docker/OCI manifest and blob API endpoints.
  • Test parsing of popular images, e.g. Alpine, Ubuntu, etc.
  • Write tests for OCI spec conformance.
  • Write tests for manifests API.
  • Write tests for blobs API.
  • Helm compatibility.
  • Make EE only?

Subreqs

  • Set up oci.pkg.keygen.sh subdomain.
  • Update dashboard.
  • Update changelog.
  • Update blog.
  • Update docs.
  • Outreach.
  • Stdout?

@ezekg ezekg force-pushed the feature/docker-engine branch 3 times, most recently from 49c2e66 to ba9255f Compare November 8, 2024 23:08
app/workers/process_docker_image_worker.rb Outdated Show resolved Hide resolved
app/workers/process_docker_image_worker.rb Outdated Show resolved Hide resolved
spec/support/matchers/upload_matcher.rb Outdated Show resolved Hide resolved
require 'minitar'
require 'zlib'

class ProcessDockerImageWorker < BaseWorker
Copy link
Member Author

Choose a reason for hiding this comment

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

This worker should be in a high_memory queue.

@ezekg ezekg force-pushed the feature/docker-engine branch 4 times, most recently from 576478c to 39740c4 Compare November 11, 2024 22:21
@ezekg ezekg force-pushed the feature/docker-engine branch 2 times, most recently from 7758cb0 to a4c8292 Compare November 15, 2024 00:10
@@ -86,6 +86,8 @@ def render_forbidden(**kwargs)

respond_to do |format|
format.any {
response.content_type = Mime::Type.lookup_by_extension(:jsonapi)
Copy link
Member Author

Choose a reason for hiding this comment

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

I think we should respond with a JSON content type if asked (or if the route uses the :json format), instead of always responding with JSONAPI.

response.content_type = Mime::Type.lookup_by_extension(:jsonapi)
in json:
in json: _
Copy link
Member Author

Choose a reason for hiding this comment

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

This can respond with JSONAPI depending on route format and accept header, since JSON and JSONAPI are often synonymous.

descriptor = package.descriptors.find_by!(content_digest: params[:digest])
authorize! descriptor.artifact

redirect_to vanity_v1_account_release_artifact_url(current_account, descriptor.artifact, filename: descriptor.content_path, host: request.host),
Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe rename this from vanity to descriptor or smth? It's more than a vanity URL now.

app/workers/process_npm_package_worker.rb Outdated Show resolved Hide resolved
MIN_TARBALL_SIZE = 512.bytes # to avoid processing empty or invalid tarballs
MAX_TARBALL_SIZE = 512.megabytes # to avoid downloading excessive tarballs
MAX_MANIFEST_SIZE = 1.megabyte # to avoid storing large manifests
MAX_BLOB_SIZE = 512.megabytes # to avoid storing large layers
Copy link
Member Author

Choose a reason for hiding this comment

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

Probably too big?

@@ -54,6 +54,14 @@ def perform(artifact_id, enqueued_at = Time.current.iso8601)
)

ProcessNpmPackageWorker.perform_async(artifact.id)
in filetype: ReleaseFiletype(:tar), engine: ReleaseEngine(:oci)
Copy link
Member Author

Choose a reason for hiding this comment

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

Support other filetypes?

Copy link
Member Author

Choose a reason for hiding this comment

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

For example tar.gz and tgz.

spec/factories/release_manifest.rb Outdated Show resolved Hide resolved
spec/support/matchers/upload_matcher.rb Outdated Show resolved Hide resolved
spec/workers/process_oci_image_worker_spec.rb Show resolved Hide resolved

expect(artifact.manifests).to satisfy { |manifests|
manifests in [
ReleaseManifest(content_path: 'index.json', content_digest: 'sha256:355eee6af939abf5ba465c9be69c3b725f8d3f19516ca9644cf2a4fb112fd83b', content_type: 'application/vnd.oci.image.index.v1+json', content_length: 441, content: String),
Copy link
Member Author

Choose a reason for hiding this comment

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

Add content asserts

end

it 'should be efficient' do
expect { subject.perform_async(artifact.id) }.to allocate_less_than(5.megabytes)
Copy link
Member Author

Choose a reason for hiding this comment

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

Refactor this to sample memory usage and assert against peak

@@ -39,7 +39,10 @@ def show
return render jsonapi: artifact if
!artifact.downloadable? || prefers?('no-download')

download = artifact.download!(ttl: release_artifact_query[:ttl])
download = artifact.download!(
filename: params.fetch(:filename) { artifact.filename },
Copy link
Member Author

Choose a reason for hiding this comment

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

Add tests.

app/models/release_artifact.rb Outdated Show resolved Hide resolved
app/models/release_manifest.rb Show resolved Hide resolved
db/migrate/20241113134529_create_release_descriptors.rb Outdated Show resolved Hide resolved
Then the response status should be "405"

@sp
Scenario: Endpoint should fail delete
Copy link
Member Author

Choose a reason for hiding this comment

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

s/delete/yank/

@buffer.clear
end

buffer.empty? ? nil : buffer
Copy link
Member Author

Choose a reason for hiding this comment

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

buffer.presence should suffice?


def self.parse(io) = Parser.new(io).parse

class DigestIO < SimpleDelegator
Copy link
Member Author

@ezekg ezekg Nov 16, 2024

Choose a reason for hiding this comment

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

Move to separate lib since it's duplicated in keygen/ee too.

end
end

class Index < Blob
Copy link
Member Author

Choose a reason for hiding this comment

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

Store manifest version?

# a Minitar::Reader, and that closes an entry's reader io after
# reading the entry. This lets us avoid buffering entries into
# memory, since some of the blobs could be large layers.
io.each do |entry|
Copy link
Member Author

Choose a reason for hiding this comment

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

Move all this outside of initializer?

io.rewind
end

def each(&)
Copy link
Member Author

Choose a reason for hiding this comment

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

Should we add return to_enum(:each) unless block_given??

algorithm: :concurrently,
unique: true

add_index :release_manifests, %i[content_type release_artifact_id],
Copy link
Member Author

Choose a reason for hiding this comment

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

Doesn't need artifact in the index.

t.index %i[release_artifact_id]
t.index %i[content_path release_artifact_id], unique: true
t.index %i[content_digest release_artifact_id], unique: true
t.index %i[content_type release_artifact_id]
Copy link
Member Author

Choose a reason for hiding this comment

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

Drop artifact from index.

disable_ddl_transaction!

def change
add_column :release_manifests, :content_path, :string, null: true
Copy link
Member Author

Choose a reason for hiding this comment

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

Eventually make these not-null.

ezekg added a commit to keygen-sh/keygen-relay that referenced this pull request Nov 26, 2024
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.

Add support for Docker/OCI container registry
1 participant