[gNOI] Add sonic.gnoi.oras.v1.Oras service (Pull RPC) + design doc (#…#713
Open
v-cshekar wants to merge 1 commit into
Open
[gNOI] Add sonic.gnoi.oras.v1.Oras service (Pull RPC) + design doc (#…#713v-cshekar wants to merge 1 commit into
v-cshekar wants to merge 1 commit into
Conversation
…onic-net#692) * doc: design for gNOI ORAS Pull service Draft RFC for a new sonic.gnoi.oras.v1.Oras service that lets an orchestrator instruct a switch to pull an OCI/ORAS artifact from a registry into local staging, decoupled from install. Tracks ADO Feature #37984064. Signed-off-by: Dawei Huang <daweihuang@microsoft.com> * doc: correct framing of SONiC TransferToRemote SONiC's TransferToRemote actually performs a download (HTTP GET into local_path), not an upload as upstream openconfig defines. Update §1 to describe the real current state and enumerate the concrete limitations that block its use for ACR/ORAS. Signed-off-by: Dawei Huang <daweihuang@microsoft.com> * proto: add sonic.gnoi.oras.v1.Oras service definition PoC subset of the ORAS Pull design (doc/oras-pull-design.md): a single streaming Pull RPC with anonymous + basic auth and an optional http_proxy field. List/Delete and richer features are deferred. Generated oras.pb.go is checked in following the existing precedent (proto/sonic.pb.go, proto/gnoi/sonic_debug.pb.go). Makefile wires the new binding into PROTO_GO_BINDINGS so make can regenerate it. Signed-off-by: Dawei Huang <daweihuang@microsoft.com> * pkg/gnoi/oras: implement Pull RPC Streaming server implementation of sonic.gnoi.oras.v1.Oras.Pull: * Resolves manifest by tag or digest against an OCI registry. * Requires single-layer artifacts (PoC scope per the design doc; SONiC OS images are single layer). * Stages the layer into a temp dir next to local_path and renames into place on success, so a failed pull never leaves a partial file at local_path. * Emits PullStarted once the manifest is resolved, PullProgress at most once per second, and a final PullResult with elapsed time and per-layer digest. * Reuses the file-server path allowlist (/tmp, /var/tmp, /host). * Supports anonymous and basic auth (ACR admin user); workload identity and bearer modes are stubbed out for v1. * http_proxy field plumbed into the HTTP transport so testbeds where the registry is not reachable via the default route (e.g. sonic-vs vlabs behind a host tinyproxy) can still pull. * Best-effort registry-error to gRPC status mapping. Adds oras.land/oras-go/v2 v2.6.0 and github.com/opencontainers/image-spec v1.1.1 to go.mod. Signed-off-by: Dawei Huang <daweihuang@microsoft.com> * gnmi_server: register sonic.gnoi.oras.v1.Oras Add OrasServer wrapper and wire it into registerAllServices behind the existing EnableTranslibWrite || EnableNativeWrite gate, alongside the other gNOI services. Pull authenticates the caller and then delegates to pkg/gnoi/oras.HandlePull. Signed-off-by: Dawei Huang <daweihuang@microsoft.com> * gnmi_server: register Oras unconditionally Drop the EnableTranslibWrite/EnableNativeWrite gate for sonic.gnoi.oras.v1.Oras. The other services inside that gate are there because gNMI write paths (translib / native YANG) should not be exposed unless the operator opted in to writes. Oras Pull does not touch any YANG datastore — it writes only into an allowlisted staging area inside the gnmi container — so the gate is not meaningful here. Keep the service available on every build, mirroring the unconditional registration of system / factory_reset. Signed-off-by: Dawei Huang <daweihuang@microsoft.com> * pkg/gnoi/oras: add unit tests, split HandlePull for testability Introduce handlePullWithRepo as a seam so tests can drive the pull loop against an httptest-backed fake registry (PlainHTTP) without reaching the real network. HandlePull keeps the same public signature, validates the request, constructs the repository, then delegates. New tests cover: - validatePullRequest (12 cases) - validateLocalPath (allowlist + traversal) - pullReference (tag vs digest precedence) - pickSingleLayer (0/1/2 layers, malformed JSON) - mapRegistryError (401/host/timeout/404/ENOSPC/default) - countingReader, copyAndRemove, jsonUnmarshalStrict - newRepository wires basic-auth credentials + leaves Credential nil for anonymous; rejects invalid registry refs - HandlePull happy path and auth-failure path against a fake registry Package coverage now 81.8%. Signed-off-by: Dawei Huang <daweihuang@microsoft.com> * pkg/gnoi/oras: gofmt oras_test.go Signed-off-by: Dawei Huang <daweihuang@microsoft.com> * pure.mk: register pkg/gnoi/oras as a pure package pkg/gnoi/oras has no CGO or SONiC dependencies, so its tests can run in the pure-test stage. Registering it here makes the pipeline pick up the unit tests and include them in the diff-coverage gate. Signed-off-by: Dawei Huang <daweihuang@microsoft.com> * pkg/gnoi/oras: expand error-branch test coverage Add tests for HandlePull wrapper (E2E + bad registry ref), multi-layer manifest rejection, MkdirTemp failure, blob fetch 500, Send error on PullStarted, and copyAndRemove dst-open error. Lifts statement coverage from 81.8% to 89.9% so the pipeline diff-coverage gate (>=80% lines) clears with comfortable margin. Signed-off-by: Dawei Huang <daweihuang@microsoft.com> * pkg/gnoi/oras: address review feedback - Serialize stream.Send through a safeStream mutex; close progressDone before final Send (and wait for the progress goroutine to exit) so the progress goroutine can never race with PullResult. - Restrict os.Rename copy-and-delete fallback to EXDEV only; surface permission / target-is-dir / etc. errors as-is instead of silently masking them. - Replace substring-based mapRegistryError with errors.As inspection of errcode.ErrorResponse, errdef.ErrNotFound, net.OpError/DNSError, net.Error.Timeout(), and syscall.ECONNREFUSED / ENOSPC. Adds PermissionDenied for 403. - validateLocalPath: walk path components for literal '..' segments instead of strings.Contains, which over-rejected names like 'a..b'. - Drop the dead '_ = oras.Copy' line and the oras-go top-level import. - Rename jsonUnmarshalStrict -> parseManifest; comment matches behavior. - proto: redact registry hostname example; move PoC-subset scope notes from the file-level comment (which protoc-gen-go places in front of the DO NOT EDIT marker) to the Oras service comment; regen pb.go. - Tests: switch hard-coded /tmp/oras-test-<pid>.bin paths to a per-test MkdirTemp helper under /tmp; rename proto_clone -> protoClone; add TestIsCrossDeviceError; rework TestMapRegistryError to use typed errors. Signed-off-by: Dawei Huang <daweihuang@microsoft.com> * pkg/gnoi/oras: drop http_proxy from PullRequest, lean on env vars http_proxy on the wire mixes ops policy into the RPC contract. Go's http.DefaultTransport already honors the standard HTTP_PROXY / HTTPS_PROXY / NO_PROXY env vars via http.ProxyFromEnvironment, and lab testbeds can inject those on the gnmi process (e.g. via /usr/bin/gnmi-native.sh). Production switches with a default route to the registry need no configuration. Also trims the design doc's PullRequest example: removes media_type_filter, source_address, source_vrf, skip_if_exists, expected_manifest_digest — all speculative v2+ knobs that don't belong in the first cut. Lists them in a 'deliberately deferred' section so the rationale is preserved. Regenerates oras.pb.go to drop field sonic-net#7. Signed-off-by: Dawei Huang <daweihuang@microsoft.com> * pkg/hostfs: add shared host-path validate + container translate helpers New /tmp/, /var/tmp/, /host/ allowlist + /mnt/host bind-mount translation lives in pkg/hostfs. pkg/gnoi/oras switches over so its writes land on the host filesystem (sonic-installer reads from the host /tmp, not the container's tmpfs). internal/diskspace and pkg/gnoi/file still have their own private copies of this logic; migrating them is a follow-up to keep this change focused. Also picks up an existing go.mod entry (opencontainers/go-digest is used directly by the oras tests; promote it from indirect). Signed-off-by: Dawei Huang <daweihuang@microsoft.com> * doc/oras-pull-design: add mermaid sequence for end-to-end Pull flow Documents how HandlePull drives oras-go through Resolve → Fetch → file.Store, where progress comes from (countingReader + 1s ticker), and why the staging dir is created next to the destination (same-fs rename). Captures hostfs.Translate as the container→host path seam. Signed-off-by: Dawei Huang <daweihuang@microsoft.com> --------- Signed-off-by: Dawei Huang <daweihuang@microsoft.com> (cherry picked from commit a42ed0d) # Conflicts: # gnmi_server/server.go # go.mod # go.sum
Contributor
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Contributor
|
Hi, there are workflow run(s) waiting for approval, you may be first-time contributor. I will notify maintainers to help approve once PR is approved. Thanks! ---Powered by SONiC BuildBot
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…692)
Draft RFC for a new sonic.gnoi.oras.v1.Oras service that lets an orchestrator instruct a switch to pull an OCI/ORAS artifact from a registry into local staging, decoupled from install.
Tracks ADO Feature #37984064.
Signed-off-by: Dawei Huang daweihuang@microsoft.com
SONiC's TransferToRemote actually performs a download (HTTP GET into local_path), not an upload as upstream openconfig defines. Update §1 to describe the real current state and enumerate the concrete limitations that block its use for ACR/ORAS.
Signed-off-by: Dawei Huang daweihuang@microsoft.com
PoC subset of the ORAS Pull design (doc/oras-pull-design.md): a single streaming Pull RPC with anonymous + basic auth and an optional http_proxy field. List/Delete and richer features are deferred.
Generated oras.pb.go is checked in following the existing precedent (proto/sonic.pb.go, proto/gnoi/sonic_debug.pb.go). Makefile wires the new binding into PROTO_GO_BINDINGS so make can regenerate it.
Signed-off-by: Dawei Huang daweihuang@microsoft.com
Streaming server implementation of sonic.gnoi.oras.v1.Oras.Pull:
Adds oras.land/oras-go/v2 v2.6.0 and github.com/opencontainers/image-spec v1.1.1 to go.mod.
Signed-off-by: Dawei Huang daweihuang@microsoft.com
Add OrasServer wrapper and wire it into registerAllServices behind the existing EnableTranslibWrite || EnableNativeWrite gate, alongside the other gNOI services. Pull authenticates the caller and then delegates to pkg/gnoi/oras.HandlePull.
Signed-off-by: Dawei Huang daweihuang@microsoft.com
Drop the EnableTranslibWrite/EnableNativeWrite gate for sonic.gnoi.oras.v1.Oras. The other services inside that gate are there because gNMI write paths (translib / native YANG) should not be exposed unless the operator opted in to writes. Oras Pull does not touch any YANG datastore — it writes only into an allowlisted staging area inside the gnmi container — so the gate is not meaningful here. Keep the service available on every build, mirroring the unconditional registration of system / factory_reset.
Signed-off-by: Dawei Huang daweihuang@microsoft.com
Introduce handlePullWithRepo as a seam so tests can drive the pull loop against an httptest-backed fake registry (PlainHTTP) without reaching the real network. HandlePull keeps the same public signature, validates the request, constructs the repository, then delegates.
New tests cover:
Package coverage now 81.8%.
Signed-off-by: Dawei Huang daweihuang@microsoft.com
Signed-off-by: Dawei Huang daweihuang@microsoft.com
pkg/gnoi/oras has no CGO or SONiC dependencies, so its tests can run in the pure-test stage. Registering it here makes the pipeline pick up the unit tests and include them in the diff-coverage gate.
Signed-off-by: Dawei Huang daweihuang@microsoft.com
Add tests for HandlePull wrapper (E2E + bad registry ref), multi-layer manifest rejection, MkdirTemp failure, blob fetch 500, Send error on PullStarted, and copyAndRemove dst-open error. Lifts statement coverage from 81.8% to 89.9% so the pipeline diff-coverage gate (>=80% lines) clears with comfortable margin.
Signed-off-by: Dawei Huang daweihuang@microsoft.com
Signed-off-by: Dawei Huang daweihuang@microsoft.com
http_proxy on the wire mixes ops policy into the RPC contract. Go's http.DefaultTransport already honors the standard HTTP_PROXY / HTTPS_PROXY / NO_PROXY env vars via http.ProxyFromEnvironment, and lab testbeds can inject those on the gnmi process (e.g. via /usr/bin/gnmi-native.sh). Production switches with a default route to the registry need no configuration.
Also trims the design doc's PullRequest example: removes media_type_filter, source_address, source_vrf, skip_if_exists, expected_manifest_digest — all speculative v2+ knobs that don't belong in the first cut. Lists them in a 'deliberately deferred' section so the rationale is preserved.
Regenerates oras.pb.go to drop field #7.
Signed-off-by: Dawei Huang daweihuang@microsoft.com
New /tmp/, /var/tmp/, /host/ allowlist + /mnt/host bind-mount translation lives in pkg/hostfs. pkg/gnoi/oras switches over so its writes land on the host filesystem (sonic-installer reads from the host /tmp, not the container's tmpfs).
internal/diskspace and pkg/gnoi/file still have their own private copies of this logic; migrating them is a follow-up to keep this change focused.
Also picks up an existing go.mod entry (opencontainers/go-digest is used directly by the oras tests; promote it from indirect).
Signed-off-by: Dawei Huang daweihuang@microsoft.com
Documents how HandlePull drives oras-go through Resolve → Fetch → file.Store, where progress comes from (countingReader + 1s ticker), and why the staging dir is created next to the destination (same-fs rename). Captures hostfs.Translate as the container→host path seam.
Signed-off-by: Dawei Huang daweihuang@microsoft.com
Signed-off-by: Dawei Huang daweihuang@microsoft.com
(cherry picked from commit a42ed0d)
Conflicts:
gnmi_server/server.go
go.mod
go.sum
Why I did it
How I did it
How to verify it
Which release branch to backport (provide reason below if selected)
Description for the changelog
Link to config_db schema for YANG module changes
A picture of a cute animal (not mandatory but encouraged)