Unverified Commit a468ae04 authored by Daniel Hiltgen's avatar Daniel Hiltgen Committed by GitHub
Browse files

Merge pull request #2499 from ollama/windows-preview

Windows Preview
parents c9ab1aea c3e62ba3
...@@ -24,13 +24,13 @@ fi ...@@ -24,13 +24,13 @@ fi
chmod +x dist/ollama chmod +x dist/ollama
# build and optionally sign the mac app # build and optionally sign the mac app
npm install --prefix app npm install --prefix macapp
if [ -n "$APPLE_IDENTITY" ]; then if [ -n "$APPLE_IDENTITY" ]; then
npm run --prefix app make:sign npm run --prefix macapp make:sign
else else
npm run --prefix app make npm run --prefix macapp make
fi fi
cp app/out/make/zip/darwin/universal/Ollama-darwin-universal-$VERSION.zip dist/Ollama-darwin.zip cp macapp/out/make/zip/darwin/universal/Ollama-darwin-universal-$VERSION.zip dist/Ollama-darwin.zip
# sign the binary and rename it # sign the binary and rename it
if [ -n "$APPLE_IDENTITY" ]; then if [ -n "$APPLE_IDENTITY" ]; then
......
...@@ -60,13 +60,17 @@ subprocess.check_call(['ssh', netloc, 'cd', path, ';', 'git', 'checkout', branch ...@@ -60,13 +60,17 @@ subprocess.check_call(['ssh', netloc, 'cd', path, ';', 'git', 'checkout', branch
# subprocess.check_call(['ssh', netloc, 'cd', path, ';', 'env']) # subprocess.check_call(['ssh', netloc, 'cd', path, ';', 'env'])
# TODO - or consider paramiko maybe # TODO - or consider paramiko maybe
print("Performing generate") print("Running Windows Build Script")
subprocess.check_call(['ssh', netloc, 'cd', path, ';', GoCmd, 'generate', './...']) subprocess.check_call(['ssh', netloc, 'cd', path, ';', "powershell", "-ExecutionPolicy", "Bypass", "-File", "./scripts/build_windows.ps1"])
print("Building") # print("Building")
subprocess.check_call(['ssh', netloc, 'cd', path, ';', GoCmd, 'build', '.']) # subprocess.check_call(['ssh', netloc, 'cd', path, ';', GoCmd, 'build', '.'])
print("Copying built result") print("Copying built result")
subprocess.check_call(['scp', netloc +":"+ path + "/ollama.exe", './dist/']) subprocess.check_call(['scp', netloc +":"+ path + "/ollama.exe", './dist/'])
print("Copying installer")
subprocess.check_call(['scp', netloc +":"+ path + "/dist/Ollama Setup.exe", './dist/'])
#!powershell
#
# powershell -ExecutionPolicy Bypass -File .\scripts\build_windows.ps1
#
# gcloud auth application-default login
$ErrorActionPreference = "Stop"
function checkEnv() {
write-host "Locating required tools and paths"
$script:SRC_DIR=$PWD
if (!$env:VCToolsRedistDir) {
$MSVC_INSTALL=(Get-CimInstance MSFT_VSInstance -Namespace root/cimv2/vs)[0].InstallLocation
$env:VCToolsRedistDir=(get-item "${MSVC_INSTALL}\VC\Redist\MSVC\*")[0]
}
$script:NVIDIA_DIR=(get-item "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v*\bin\")[0]
$script:INNO_SETUP_DIR=(get-item "C:\Program Files*\Inno Setup*\")[0]
$script:DEPS_DIR="${script:SRC_DIR}\dist\windeps"
$env:CGO_ENABLED="1"
echo "Checking version"
if (!$env:VERSION) {
$data=(git describe --tags --first-parent --abbrev=7 --long --dirty --always)
$pattern="v(.+)"
if ($data -match $pattern) {
$script:VERSION=$matches[1]
}
} else {
$script:VERSION=$env:VERSION
}
$pattern = "(\d+[.]\d+[.]\d+)-(\d+)-"
if ($script:VERSION -match $pattern) {
$script:PKG_VERSION=$matches[1] + "." + $matches[2]
} else {
$script:PKG_VERSION=$script:VERSION
}
write-host "Building Ollama $script:VERSION with package version $script:PKG_VERSION"
# Check for signing key
if ("${env:KEY_CONTAINER}") {
${env:OLLAMA_CERT}=$(resolve-path "${script:SRC_DIR}\ollama_inc.crt")
Write-host "Code signing enabled"
# Note: 10 Windows Kit signtool crashes with GCP's plugin
${script:SignTool}="C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe"
} else {
write-host "Code signing disabled - please set KEY_CONTAINERS to sign and copy ollama_inc.crt to the top of the source tree"
}
}
function buildOllama() {
write-host "Building ollama CLI"
& go generate ./...
if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
& go build "-ldflags=-w -s ""-X=github.com/jmorganca/ollama/version.Version=$script:VERSION"" ""-X=github.com/jmorganca/ollama/server.mode=release""" .
if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
if ("${env:KEY_CONTAINER}") {
& "${script:SignTool}" sign /v /fd sha256 /t http://timestamp.digicert.com /f "${env:OLLAMA_CERT}" `
/csp "Google Cloud KMS Provider" /kc ${env:KEY_CONTAINER} ollama.exe
if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
}
cp .\ollama.exe .\dist\ollama-windows-amd64.exe
}
function buildApp() {
write-host "Building Ollama App"
cd "${script:SRC_DIR}\app"
& windres -l 0 -o ollama.syso ollama.rc
& go build "-ldflags=-H windowsgui -w -s ""-X=github.com/jmorganca/ollama/version.Version=$script:VERSION"" ""-X=github.com/jmorganca/ollama/server.mode=release""" .
if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
if ("${env:KEY_CONTAINER}") {
& "${script:SignTool}" sign /v /fd sha256 /t http://timestamp.digicert.com /f "${env:OLLAMA_CERT}" `
/csp "Google Cloud KMS Provider" /kc ${env:KEY_CONTAINER} app.exe
if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
}
}
function gatherDependencies() {
write-host "Gathering runtime dependencies"
cd "${script:SRC_DIR}"
rm -ea 0 -recurse -force -path "${script:DEPS_DIR}"
md "${script:DEPS_DIR}" -ea 0 > $null
# TODO - this varies based on host build system and MSVC version - drive from dumpbin output
# currently works for Win11 + MSVC 2019 + Cuda V11
cp "${env:VCToolsRedistDir}\x64\Microsoft.VC*.CRT\msvcp140.dll" "${script:DEPS_DIR}\"
cp "${env:VCToolsRedistDir}\x64\Microsoft.VC*.CRT\vcruntime140.dll" "${script:DEPS_DIR}\"
cp "${env:VCToolsRedistDir}\x64\Microsoft.VC*.CRT\vcruntime140_1.dll" "${script:DEPS_DIR}\"
cp "${script:NVIDIA_DIR}\cudart64_*.dll" "${script:DEPS_DIR}\"
cp "${script:NVIDIA_DIR}\cublas64_*.dll" "${script:DEPS_DIR}\"
cp "${script:NVIDIA_DIR}\cublasLt64_*.dll" "${script:DEPS_DIR}\"
cp "${script:SRC_DIR}\app\ollama_welcome.ps1" "${script:SRC_DIR}\dist\"
if ("${env:KEY_CONTAINER}") {
write-host "about to sign"
foreach ($file in (get-childitem "${script:DEPS_DIR}/cu*.dll") + @("${script:SRC_DIR}\dist\ollama_welcome.ps1")){
write-host "signing $file"
& "${script:SignTool}" sign /v /fd sha256 /t http://timestamp.digicert.com /f "${env:OLLAMA_CERT}" `
/csp "Google Cloud KMS Provider" /kc ${env:KEY_CONTAINER} $file
if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
}
}
}
function buildInstaller() {
write-host "Building Ollama Installer"
cd "${script:SRC_DIR}\app"
$env:PKG_VERSION=$script:PKG_VERSION
if ("${env:KEY_CONTAINER}") {
& "${script:INNO_SETUP_DIR}\ISCC.exe" /SMySignTool="${script:SignTool} sign /fd sha256 /t http://timestamp.digicert.com /f ${env:OLLAMA_CERT} /csp `$qGoogle Cloud KMS Provider`$q /kc ${env:KEY_CONTAINER} `$f" .\ollama.iss
} else {
& "${script:INNO_SETUP_DIR}\ISCC.exe" .\ollama.iss
}
if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
}
try {
checkEnv
buildOllama
buildApp
gatherDependencies
buildInstaller
} catch {
write-host "Build Failed"
write-host $_
} finally {
set-location $script:SRC_DIR
$env:PKG_VERSION=""
}
\ No newline at end of file
package server package server
import ( import (
"bytes"
"context" "context"
"crypto/rand" "crypto/rand"
"crypto/sha256" "crypto/sha256"
...@@ -10,167 +9,87 @@ import ( ...@@ -10,167 +9,87 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"log/slog"
"net/http" "net/http"
"net/url" "net/url"
"os"
"path/filepath"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"golang.org/x/crypto/ssh"
"github.com/jmorganca/ollama/api" "github.com/jmorganca/ollama/api"
"github.com/jmorganca/ollama/auth"
) )
type AuthRedirect struct { type registryChallenge struct {
Realm string Realm string
Service string Service string
Scope string Scope string
} }
type SignatureData struct { func (r registryChallenge) URL() (*url.URL, error) {
Method string
Path string
Data []byte
}
func generateNonce(length int) (string, error) {
nonce := make([]byte, length)
_, err := rand.Read(nonce)
if err != nil {
return "", err
}
return base64.RawURLEncoding.EncodeToString(nonce), nil
}
func (r AuthRedirect) URL() (*url.URL, error) {
redirectURL, err := url.Parse(r.Realm) redirectURL, err := url.Parse(r.Realm)
if err != nil { if err != nil {
return nil, err return nil, err
} }
values := redirectURL.Query() values := redirectURL.Query()
values.Add("service", r.Service) values.Add("service", r.Service)
for _, s := range strings.Split(r.Scope, " ") { for _, s := range strings.Split(r.Scope, " ") {
values.Add("scope", s) values.Add("scope", s)
} }
values.Add("ts", strconv.FormatInt(time.Now().Unix(), 10)) values.Add("ts", strconv.FormatInt(time.Now().Unix(), 10))
nonce, err := generateNonce(16) nonce, err := auth.NewNonce(rand.Reader, 16)
if err != nil { if err != nil {
return nil, err return nil, err
} }
values.Add("nonce", nonce) values.Add("nonce", nonce)
redirectURL.RawQuery = values.Encode() redirectURL.RawQuery = values.Encode()
return redirectURL, nil return redirectURL, nil
} }
func getAuthToken(ctx context.Context, redirData AuthRedirect) (string, error) { func getAuthorizationToken(ctx context.Context, challenge registryChallenge) (string, error) {
redirectURL, err := redirData.URL() redirectURL, err := challenge.URL()
if err != nil { if err != nil {
return "", err return "", err
} }
home, err := os.UserHomeDir() sha256sum := sha256.Sum256(nil)
if err != nil { data := []byte(fmt.Sprintf("%s,%s,%s", http.MethodGet, redirectURL.String(), base64.StdEncoding.EncodeToString([]byte(hex.EncodeToString(sha256sum[:])))))
return "", err
}
keyPath := filepath.Join(home, ".ollama", "id_ed25519")
rawKey, err := os.ReadFile(keyPath)
if err != nil {
slog.Info(fmt.Sprintf("Failed to load private key: %v", err))
return "", err
}
s := SignatureData{
Method: http.MethodGet,
Path: redirectURL.String(),
Data: nil,
}
sig, err := s.Sign(rawKey)
if err != nil {
return "", err
}
headers := make(http.Header) headers := make(http.Header)
headers.Set("Authorization", sig) signature, err := auth.Sign(ctx, data)
resp, err := makeRequest(ctx, http.MethodGet, redirectURL, headers, nil, nil)
if err != nil { if err != nil {
slog.Info(fmt.Sprintf("couldn't get token: %q", err))
return "", err return "", err
} }
defer resp.Body.Close()
if resp.StatusCode >= http.StatusBadRequest { headers.Add("Authorization", signature)
responseBody, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("%d: %v", resp.StatusCode, err)
} else if len(responseBody) > 0 {
return "", fmt.Errorf("%d: %s", resp.StatusCode, responseBody)
}
return "", fmt.Errorf("%s", resp.Status) response, err := makeRequest(ctx, http.MethodGet, redirectURL, headers, nil, nil)
}
respBody, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
return "", err return "", err
} }
defer response.Body.Close()
var tok api.TokenResponse body, err := io.ReadAll(response.Body)
if err := json.Unmarshal(respBody, &tok); err != nil {
return "", err
}
return tok.Token, nil
}
// Bytes returns a byte slice of the data to sign for the request
func (s SignatureData) Bytes() []byte {
// We first derive the content hash of the request body using:
// base64(hex(sha256(request body)))
hash := sha256.Sum256(s.Data)
hashHex := make([]byte, hex.EncodedLen(len(hash)))
hex.Encode(hashHex, hash[:])
contentHash := base64.StdEncoding.EncodeToString(hashHex)
// We then put the entire request together in a serialize string using:
// "<method>,<uri>,<content hash>"
// e.g. "GET,http://localhost,OTdkZjM1O..."
return []byte(strings.Join([]string{s.Method, s.Path, contentHash}, ","))
}
// SignData takes a SignatureData object and signs it with a raw private key
func (s SignatureData) Sign(rawKey []byte) (string, error) {
signer, err := ssh.ParsePrivateKey(rawKey)
if err != nil { if err != nil {
return "", err return "", fmt.Errorf("%d: %v", response.StatusCode, err)
} }
// get the pubkey, but remove the type if response.StatusCode >= http.StatusBadRequest {
pubKey := ssh.MarshalAuthorizedKey(signer.PublicKey()) if len(body) > 0 {
parts := bytes.Split(pubKey, []byte(" ")) return "", fmt.Errorf("%d: %s", response.StatusCode, body)
if len(parts) < 2 { } else {
return "", fmt.Errorf("malformed public key") return "", fmt.Errorf("%d", response.StatusCode)
}
} }
signedData, err := signer.Sign(nil, s.Bytes()) var token api.TokenResponse
if err != nil { if err := json.Unmarshal(body, &token); err != nil {
return "", err return "", err
} }
// signature is <pubkey>:<signature> return token.Token, nil
sig := fmt.Sprintf("%s:%s", bytes.TrimSpace(parts[1]), base64.StdEncoding.EncodeToString(signedData.Blob))
return sig, nil
} }
...@@ -85,7 +85,7 @@ func (p *blobDownloadPart) Write(b []byte) (n int, err error) { ...@@ -85,7 +85,7 @@ func (p *blobDownloadPart) Write(b []byte) (n int, err error) {
return n, nil return n, nil
} }
func (b *blobDownload) Prepare(ctx context.Context, requestURL *url.URL, opts *RegistryOptions) error { func (b *blobDownload) Prepare(ctx context.Context, requestURL *url.URL, opts *registryOptions) error {
partFilePaths, err := filepath.Glob(b.Name + "-partial-*") partFilePaths, err := filepath.Glob(b.Name + "-partial-*")
if err != nil { if err != nil {
return err return err
...@@ -137,11 +137,11 @@ func (b *blobDownload) Prepare(ctx context.Context, requestURL *url.URL, opts *R ...@@ -137,11 +137,11 @@ func (b *blobDownload) Prepare(ctx context.Context, requestURL *url.URL, opts *R
return nil return nil
} }
func (b *blobDownload) Run(ctx context.Context, requestURL *url.URL, opts *RegistryOptions) { func (b *blobDownload) Run(ctx context.Context, requestURL *url.URL, opts *registryOptions) {
b.err = b.run(ctx, requestURL, opts) b.err = b.run(ctx, requestURL, opts)
} }
func (b *blobDownload) run(ctx context.Context, requestURL *url.URL, opts *RegistryOptions) error { func (b *blobDownload) run(ctx context.Context, requestURL *url.URL, opts *registryOptions) error {
defer blobDownloadManager.Delete(b.Digest) defer blobDownloadManager.Delete(b.Digest)
ctx, b.CancelFunc = context.WithCancel(ctx) ctx, b.CancelFunc = context.WithCancel(ctx)
...@@ -210,7 +210,7 @@ func (b *blobDownload) run(ctx context.Context, requestURL *url.URL, opts *Regis ...@@ -210,7 +210,7 @@ func (b *blobDownload) run(ctx context.Context, requestURL *url.URL, opts *Regis
return nil return nil
} }
func (b *blobDownload) downloadChunk(ctx context.Context, requestURL *url.URL, w io.Writer, part *blobDownloadPart, opts *RegistryOptions) error { func (b *blobDownload) downloadChunk(ctx context.Context, requestURL *url.URL, w io.Writer, part *blobDownloadPart, opts *registryOptions) error {
g, ctx := errgroup.WithContext(ctx) g, ctx := errgroup.WithContext(ctx)
g.Go(func() error { g.Go(func() error {
headers := make(http.Header) headers := make(http.Header)
...@@ -334,7 +334,7 @@ func (b *blobDownload) Wait(ctx context.Context, fn func(api.ProgressResponse)) ...@@ -334,7 +334,7 @@ func (b *blobDownload) Wait(ctx context.Context, fn func(api.ProgressResponse))
type downloadOpts struct { type downloadOpts struct {
mp ModelPath mp ModelPath
digest string digest string
regOpts *RegistryOptions regOpts *registryOptions
fn func(api.ProgressResponse) fn func(api.ProgressResponse)
} }
......
...@@ -28,7 +28,7 @@ import ( ...@@ -28,7 +28,7 @@ import (
"github.com/jmorganca/ollama/version" "github.com/jmorganca/ollama/version"
) )
type RegistryOptions struct { type registryOptions struct {
Insecure bool Insecure bool
Username string Username string
Password string Password string
...@@ -320,7 +320,7 @@ func CreateModel(ctx context.Context, name, modelFileDir string, commands []pars ...@@ -320,7 +320,7 @@ func CreateModel(ctx context.Context, name, modelFileDir string, commands []pars
switch { switch {
case errors.Is(err, os.ErrNotExist): case errors.Is(err, os.ErrNotExist):
fn(api.ProgressResponse{Status: "pulling model"}) fn(api.ProgressResponse{Status: "pulling model"})
if err := PullModel(ctx, c.Args, &RegistryOptions{}, fn); err != nil { if err := PullModel(ctx, c.Args, &registryOptions{}, fn); err != nil {
return err return err
} }
...@@ -840,7 +840,7 @@ PARAMETER {{ $k }} {{ printf "%#v" $parameter }} ...@@ -840,7 +840,7 @@ PARAMETER {{ $k }} {{ printf "%#v" $parameter }}
return buf.String(), nil return buf.String(), nil
} }
func PushModel(ctx context.Context, name string, regOpts *RegistryOptions, fn func(api.ProgressResponse)) error { func PushModel(ctx context.Context, name string, regOpts *registryOptions, fn func(api.ProgressResponse)) error {
mp := ParseModelPath(name) mp := ParseModelPath(name)
fn(api.ProgressResponse{Status: "retrieving manifest"}) fn(api.ProgressResponse{Status: "retrieving manifest"})
...@@ -890,7 +890,7 @@ func PushModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu ...@@ -890,7 +890,7 @@ func PushModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
return nil return nil
} }
func PullModel(ctx context.Context, name string, regOpts *RegistryOptions, fn func(api.ProgressResponse)) error { func PullModel(ctx context.Context, name string, regOpts *registryOptions, fn func(api.ProgressResponse)) error {
mp := ParseModelPath(name) mp := ParseModelPath(name)
var manifest *ManifestV2 var manifest *ManifestV2
...@@ -996,7 +996,7 @@ func PullModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu ...@@ -996,7 +996,7 @@ func PullModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
return nil return nil
} }
func pullModelManifest(ctx context.Context, mp ModelPath, regOpts *RegistryOptions) (*ManifestV2, error) { func pullModelManifest(ctx context.Context, mp ModelPath, regOpts *registryOptions) (*ManifestV2, error) {
requestURL := mp.BaseURL().JoinPath("v2", mp.GetNamespaceRepository(), "manifests", mp.Tag) requestURL := mp.BaseURL().JoinPath("v2", mp.GetNamespaceRepository(), "manifests", mp.Tag)
headers := make(http.Header) headers := make(http.Header)
...@@ -1028,7 +1028,7 @@ func GetSHA256Digest(r io.Reader) (string, int64) { ...@@ -1028,7 +1028,7 @@ func GetSHA256Digest(r io.Reader) (string, int64) {
var errUnauthorized = fmt.Errorf("unauthorized") var errUnauthorized = fmt.Errorf("unauthorized")
func makeRequestWithRetry(ctx context.Context, method string, requestURL *url.URL, headers http.Header, body io.ReadSeeker, regOpts *RegistryOptions) (*http.Response, error) { func makeRequestWithRetry(ctx context.Context, method string, requestURL *url.URL, headers http.Header, body io.ReadSeeker, regOpts *registryOptions) (*http.Response, error) {
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
resp, err := makeRequest(ctx, method, requestURL, headers, body, regOpts) resp, err := makeRequest(ctx, method, requestURL, headers, body, regOpts)
if err != nil { if err != nil {
...@@ -1042,9 +1042,8 @@ func makeRequestWithRetry(ctx context.Context, method string, requestURL *url.UR ...@@ -1042,9 +1042,8 @@ func makeRequestWithRetry(ctx context.Context, method string, requestURL *url.UR
switch { switch {
case resp.StatusCode == http.StatusUnauthorized: case resp.StatusCode == http.StatusUnauthorized:
// Handle authentication error with one retry // Handle authentication error with one retry
auth := resp.Header.Get("www-authenticate") challenge := parseRegistryChallenge(resp.Header.Get("www-authenticate"))
authRedir := ParseAuthRedirectString(auth) token, err := getAuthorizationToken(ctx, challenge)
token, err := getAuthToken(ctx, authRedir)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -1071,7 +1070,7 @@ func makeRequestWithRetry(ctx context.Context, method string, requestURL *url.UR ...@@ -1071,7 +1070,7 @@ func makeRequestWithRetry(ctx context.Context, method string, requestURL *url.UR
return nil, errUnauthorized return nil, errUnauthorized
} }
func makeRequest(ctx context.Context, method string, requestURL *url.URL, headers http.Header, body io.Reader, regOpts *RegistryOptions) (*http.Response, error) { func makeRequest(ctx context.Context, method string, requestURL *url.URL, headers http.Header, body io.Reader, regOpts *registryOptions) (*http.Response, error) {
if requestURL.Scheme != "http" && regOpts != nil && regOpts.Insecure { if requestURL.Scheme != "http" && regOpts != nil && regOpts.Insecure {
requestURL.Scheme = "http" requestURL.Scheme = "http"
} }
...@@ -1146,10 +1145,10 @@ func getValue(header, key string) string { ...@@ -1146,10 +1145,10 @@ func getValue(header, key string) string {
return header[startIdx:endIdx] return header[startIdx:endIdx]
} }
func ParseAuthRedirectString(authStr string) AuthRedirect { func parseRegistryChallenge(authStr string) registryChallenge {
authStr = strings.TrimPrefix(authStr, "Bearer ") authStr = strings.TrimPrefix(authStr, "Bearer ")
return AuthRedirect{ return registryChallenge{
Realm: getValue(authStr, "realm"), Realm: getValue(authStr, "realm"),
Service: getValue(authStr, "service"), Service: getValue(authStr, "service"),
Scope: getValue(authStr, "scope"), Scope: getValue(authStr, "scope"),
......
...@@ -479,7 +479,7 @@ func PullModelHandler(c *gin.Context) { ...@@ -479,7 +479,7 @@ func PullModelHandler(c *gin.Context) {
ch <- r ch <- r
} }
regOpts := &RegistryOptions{ regOpts := &registryOptions{
Insecure: req.Insecure, Insecure: req.Insecure,
} }
...@@ -528,7 +528,7 @@ func PushModelHandler(c *gin.Context) { ...@@ -528,7 +528,7 @@ func PushModelHandler(c *gin.Context) {
ch <- r ch <- r
} }
regOpts := &RegistryOptions{ regOpts := &registryOptions{
Insecure: req.Insecure, Insecure: req.Insecure,
} }
......
...@@ -49,7 +49,7 @@ const ( ...@@ -49,7 +49,7 @@ const (
maxUploadPartSize int64 = 1000 * format.MegaByte maxUploadPartSize int64 = 1000 * format.MegaByte
) )
func (b *blobUpload) Prepare(ctx context.Context, requestURL *url.URL, opts *RegistryOptions) error { func (b *blobUpload) Prepare(ctx context.Context, requestURL *url.URL, opts *registryOptions) error {
p, err := GetBlobsPath(b.Digest) p, err := GetBlobsPath(b.Digest)
if err != nil { if err != nil {
return err return err
...@@ -121,7 +121,7 @@ func (b *blobUpload) Prepare(ctx context.Context, requestURL *url.URL, opts *Reg ...@@ -121,7 +121,7 @@ func (b *blobUpload) Prepare(ctx context.Context, requestURL *url.URL, opts *Reg
// Run uploads blob parts to the upstream. If the upstream supports redirection, parts will be uploaded // Run uploads blob parts to the upstream. If the upstream supports redirection, parts will be uploaded
// in parallel as defined by Prepare. Otherwise, parts will be uploaded serially. Run sets b.err on error. // in parallel as defined by Prepare. Otherwise, parts will be uploaded serially. Run sets b.err on error.
func (b *blobUpload) Run(ctx context.Context, opts *RegistryOptions) { func (b *blobUpload) Run(ctx context.Context, opts *registryOptions) {
defer blobUploadManager.Delete(b.Digest) defer blobUploadManager.Delete(b.Digest)
ctx, b.CancelFunc = context.WithCancel(ctx) ctx, b.CancelFunc = context.WithCancel(ctx)
...@@ -212,7 +212,7 @@ func (b *blobUpload) Run(ctx context.Context, opts *RegistryOptions) { ...@@ -212,7 +212,7 @@ func (b *blobUpload) Run(ctx context.Context, opts *RegistryOptions) {
b.done = true b.done = true
} }
func (b *blobUpload) uploadPart(ctx context.Context, method string, requestURL *url.URL, part *blobUploadPart, opts *RegistryOptions) error { func (b *blobUpload) uploadPart(ctx context.Context, method string, requestURL *url.URL, part *blobUploadPart, opts *registryOptions) error {
headers := make(http.Header) headers := make(http.Header)
headers.Set("Content-Type", "application/octet-stream") headers.Set("Content-Type", "application/octet-stream")
headers.Set("Content-Length", fmt.Sprintf("%d", part.Size)) headers.Set("Content-Length", fmt.Sprintf("%d", part.Size))
...@@ -277,9 +277,8 @@ func (b *blobUpload) uploadPart(ctx context.Context, method string, requestURL * ...@@ -277,9 +277,8 @@ func (b *blobUpload) uploadPart(ctx context.Context, method string, requestURL *
case resp.StatusCode == http.StatusUnauthorized: case resp.StatusCode == http.StatusUnauthorized:
w.Rollback() w.Rollback()
auth := resp.Header.Get("www-authenticate") challenge := parseRegistryChallenge(resp.Header.Get("www-authenticate"))
authRedir := ParseAuthRedirectString(auth) token, err := getAuthorizationToken(ctx, challenge)
token, err := getAuthToken(ctx, authRedir)
if err != nil { if err != nil {
return err return err
} }
...@@ -364,7 +363,7 @@ func (p *progressWriter) Rollback() { ...@@ -364,7 +363,7 @@ func (p *progressWriter) Rollback() {
p.written = 0 p.written = 0
} }
func uploadBlob(ctx context.Context, mp ModelPath, layer *Layer, opts *RegistryOptions, fn func(api.ProgressResponse)) error { func uploadBlob(ctx context.Context, mp ModelPath, layer *Layer, opts *registryOptions, fn func(api.ProgressResponse)) error {
requestURL := mp.BaseURL() requestURL := mp.BaseURL()
requestURL = requestURL.JoinPath("v2", mp.GetNamespaceRepository(), "blobs", layer.Digest) requestURL = requestURL.JoinPath("v2", mp.GetNamespaceRepository(), "blobs", layer.Digest)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment