Add PullCommand to githttp package
Adding PullCommand through HTTP client.
I got one last MR to go. Implementing running gitlab.com/gitlab-org/gitlab-shell/v14/internal/command/pull
PullCommand#execute
in gitlab.com/gitlab-org/gitlab-shell/v14/internal/command/uploadpack
Command#execute
before closing this issue.
Related issue: #656 (closed)
Before
When a user performs a Git pull/clone over SSH request to secondary node, Gitlab Shell performs requests to secondary Workhorse & Rails which performs a Git over HTTP request to primary.
sequenceDiagram
participant C as Git on client
participant S as GitLab Shell
participant I as Workhorse & Rails
participant P as Workhorse & Rails
Note left of C: git pull/clone
Note over S,I: Secondary site
Note over P: Primary site
C->>+S: ssh git upload-pack request
S->>I: SSH key validation (api/v4/internal/authorized_keys?key=..)
I-->>S: HTTP/1.1 300 (custom action status) with {endpoint, msg, primary_repo}
S->>I: POST /api/v4/geo/proxy_git_ssh/info_refs_upload_pack
I->>P: POST $PRIMARY/foo/bar.git/info/refs/?service=git-upload-pack
P-->>I: HTTP/1.1 200 OK
I-->>S: <response>
S-->>C: return Git response from primary
C-->>S: stream Git data to pull
S->>I: POST /api/v4/geo/proxy_git_ssh/upload_pack
I->>P: POST $PRIMARY/foo/bar.git/git-upload-pack
P-->>I: HTTP/1.1 200 OK
I-->>S: <response>
S-->>-C: gitlab-shell upload-pack response
After
When a user performs a Git pull/clone over SSH request to secondary node, Gitlab Shell performs Git over HTTP requests to primary Workhorse & Rails.
sequenceDiagram
participant C as Git on client
participant S as GitLab Shell
participant I as Workhorse & Rails
participant P as Workhorse & Rails
Note left of C: git pull/clone
Note over S,I: Secondary site
Note over P: Primary site
C->>+S: ssh git upload-pack request
S->>I: SSH key validation (api/v4/internal/authorized_keys?key=..)
I-->>S: HTTP/1.1 300 (custom action status) with {endpoint, msg, primary_repo, authorization headers}
S->>P: POST $PRIMARY/foo/bar.git/info/refs/?service=git-upload-pack
P-->>S: HTTP/1.1 200 OK
P-->>S: <response>
S-->>C: return Git response from primary
C-->>S: stream Git data to pull
S->>P: POST $PRIMARY/foo/bar.git/git-upload-pack
P-->>S: HTTP/1.1 200 OK
P-->>S: <response>
S-->>-C: gitlab-shell upload-pack response
Solution
The solution is similar to the one provided in Perform Git over HTTP request to primary repo (!716 - merged).
- We need to modify internal/command/uploadpack/uploadpack.go and call a command similar to this one. It probably should be controlled by a different feature flag.
- A separate
PullCommand
should be implemented, similar toPushCommand
. The info-refs and git-upload-pack responses should be converted according to this logic. It's similar to the following transformation (Rails logic -> Gitlab Shell logic) - HTTP client for info-refs can be reused, an additional one for upload-pack should be implemented similar to receive-pack
This MR implements this solution.
Availability and Testing
- Install Geo https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/geo.md
- In the secondary GDK/gitlab-shell directory, checkout this MR's branch
gdk start
-
gdk stop sshd
(because we will compile it and run it manually) -
make && bin/gitlab-sshd -config-dir=.
from GitLab Shell - Perform Git operations over SSH against the secondary's GitLab Shell
- Observe logs
- Enable
geo_proxy_fetch_direct_to_primary
feature flag on Rails on the primary GDK (it should propagate to the secondary) - Perform Git operations again
- Observe logs-- the trip through the secondary's GitLab Rails should now be skipped