Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
ollama
Commits
a468ae04
Unverified
Commit
a468ae04
authored
Feb 15, 2024
by
Daniel Hiltgen
Committed by
GitHub
Feb 15, 2024
Browse files
Merge pull request #2499 from ollama/windows-preview
Windows Preview
parents
c9ab1aea
c3e62ba3
Changes
89
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
192 additions
and
139 deletions
+192
-139
macapp/webpack.rules.ts
macapp/webpack.rules.ts
+0
-0
scripts/build_darwin.sh
scripts/build_darwin.sh
+4
-4
scripts/build_remote.py
scripts/build_remote.py
+8
-4
scripts/build_windows.ps1
scripts/build_windows.ps1
+132
-0
server/auth.go
server/auth.go
+24
-105
server/download.go
server/download.go
+5
-5
server/images.go
server/images.go
+11
-12
server/routes.go
server/routes.go
+2
-2
server/upload.go
server/upload.go
+6
-7
No files found.
app/webpack.rules.ts
→
mac
app/webpack.rules.ts
View file @
a468ae04
File moved
scripts/build_darwin.sh
View file @
a468ae04
...
...
@@ -24,13 +24,13 @@ fi
chmod
+x dist/ollama
# build and optionally sign the mac app
npm
install
--prefix
app
npm
install
--prefix
mac
app
if
[
-n
"
$APPLE_IDENTITY
"
]
;
then
npm run
--prefix
app make:sign
npm run
--prefix
mac
app make:sign
else
npm run
--prefix
app make
npm run
--prefix
mac
app make
fi
cp
app/out/make/zip/darwin/universal/Ollama-darwin-universal-
$VERSION
.zip dist/Ollama-darwin.zip
cp
mac
app/out/make/zip/darwin/universal/Ollama-darwin-universal-
$VERSION
.zip dist/Ollama-darwin.zip
# sign the binary and rename it
if
[
-n
"
$APPLE_IDENTITY
"
]
;
then
...
...
scripts/build_remote.py
View file @
a468ae04
...
...
@@ -60,13 +60,17 @@ subprocess.check_call(['ssh', netloc, 'cd', path, ';', 'git', 'checkout', branch
# subprocess.check_call(['ssh', netloc, 'cd', path, ';', 'env'])
# TODO - or consider paramiko maybe
print
(
"
Performing generate
"
)
subprocess
.
check_call
([
'ssh'
,
netloc
,
'cd'
,
path
,
';'
,
GoCmd
,
'generate'
,
'
./
...'
])
print
(
"
Running Windows Build Script
"
)
subprocess
.
check_call
([
'ssh'
,
netloc
,
'cd'
,
path
,
';'
,
"powershell"
,
"-ExecutionPolicy"
,
"Bypass"
,
"-File"
,
"
./
scripts/build_windows.ps1"
])
print
(
"Building"
)
subprocess
.
check_call
([
'ssh'
,
netloc
,
'cd'
,
path
,
';'
,
GoCmd
,
'build'
,
'.'
])
#
print("Building")
#
subprocess.check_call(['ssh', netloc, 'cd', path, ';', GoCmd, 'build', '.'])
print
(
"Copying built result"
)
subprocess
.
check_call
([
'scp'
,
netloc
+
":"
+
path
+
"/ollama.exe"
,
'./dist/'
])
print
(
"Copying installer"
)
subprocess
.
check_call
([
'scp'
,
netloc
+
":"
+
path
+
"/dist/Ollama Setup.exe"
,
'./dist/'
])
scripts/build_windows.ps1
0 → 100644
View file @
a468ae04
#!powershell
#
# powershell -ExecutionPolicy Bypass -File .\scripts\build_windows.ps1
#
# gcloud auth application-default login
$Error
ActionPreference
=
"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
server/auth.go
View file @
a468ae04
package
server
import
(
"bytes"
"context"
"crypto/rand"
"crypto/sha256"
...
...
@@ -10,167 +9,87 @@ import (
"encoding/json"
"fmt"
"io"
"log/slog"
"net/http"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"golang.org/x/crypto/ssh"
"github.com/jmorganca/ollama/api"
"github.com/jmorganca/ollama/auth"
)
type
AuthRedirect
struct
{
type
registryChallenge
struct
{
Realm
string
Service
string
Scope
string
}
type
SignatureData
struct
{
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
)
{
func
(
r
registryChallenge
)
URL
()
(
*
url
.
URL
,
error
)
{
redirectURL
,
err
:=
url
.
Parse
(
r
.
Realm
)
if
err
!=
nil
{
return
nil
,
err
}
values
:=
redirectURL
.
Query
()
values
.
Add
(
"service"
,
r
.
Service
)
for
_
,
s
:=
range
strings
.
Split
(
r
.
Scope
,
" "
)
{
values
.
Add
(
"scope"
,
s
)
}
values
.
Add
(
"ts"
,
strconv
.
FormatInt
(
time
.
Now
()
.
Unix
(),
10
))
nonce
,
err
:=
generateNonce
(
16
)
nonce
,
err
:=
auth
.
NewNonce
(
rand
.
Reader
,
16
)
if
err
!=
nil
{
return
nil
,
err
}
values
.
Add
(
"nonce"
,
nonce
)
redirectURL
.
RawQuery
=
values
.
Encode
()
return
redirectURL
,
nil
}
func
getAuthToken
(
ctx
context
.
Context
,
redirData
AuthRedirect
)
(
string
,
error
)
{
redirectURL
,
err
:=
redirData
.
URL
()
if
err
!=
nil
{
return
""
,
err
}
home
,
err
:=
os
.
UserHomeDir
()
if
err
!=
nil
{
return
""
,
err
}
keyPath
:=
filepath
.
Join
(
home
,
".ollama"
,
"id_ed25519"
)
rawKey
,
err
:=
os
.
ReadFile
(
keyPath
)
func
getAuthorizationToken
(
ctx
context
.
Context
,
challenge
registryChallenge
)
(
string
,
error
)
{
redirectURL
,
err
:=
challenge
.
URL
()
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
}
sha256sum
:=
sha256
.
Sum256
(
nil
)
data
:=
[]
byte
(
fmt
.
Sprintf
(
"%s,%s,%s"
,
http
.
MethodGet
,
redirectURL
.
String
(),
base64
.
StdEncoding
.
EncodeToString
([]
byte
(
hex
.
EncodeToString
(
sha256sum
[
:
])))))
headers
:=
make
(
http
.
Header
)
headers
.
Set
(
"Authorization"
,
sig
)
resp
,
err
:=
makeRequest
(
ctx
,
http
.
MethodGet
,
redirectURL
,
headers
,
nil
,
nil
)
signature
,
err
:=
auth
.
Sign
(
ctx
,
data
)
if
err
!=
nil
{
slog
.
Info
(
fmt
.
Sprintf
(
"couldn't get token: %q"
,
err
))
return
""
,
err
}
defer
resp
.
Body
.
Close
()
if
resp
.
StatusCode
>=
http
.
StatusBadRequest
{
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
)
}
headers
.
Add
(
"Authorization"
,
signature
)
resp
Body
,
err
:=
io
.
ReadAll
(
resp
.
Body
)
resp
onse
,
err
:=
makeRequest
(
ctx
,
http
.
MethodGet
,
redirectURL
,
headers
,
nil
,
nil
)
if
err
!=
nil
{
return
""
,
err
}
defer
response
.
Body
.
Close
()
var
tok
api
.
TokenResponse
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
)
body
,
err
:=
io
.
ReadAll
(
response
.
Body
)
if
err
!=
nil
{
return
""
,
err
return
""
,
fmt
.
Errorf
(
"%d: %v"
,
response
.
StatusCode
,
err
)
}
// get the pubkey, but remove the type
pubKey
:=
ssh
.
MarshalAuthorizedKey
(
signer
.
PublicKey
())
parts
:=
bytes
.
Split
(
pubKey
,
[]
byte
(
" "
))
if
len
(
parts
)
<
2
{
return
""
,
fmt
.
Errorf
(
"malformed public key"
)
if
response
.
StatusCode
>=
http
.
StatusBadRequest
{
if
len
(
body
)
>
0
{
return
""
,
fmt
.
Errorf
(
"%d: %s"
,
response
.
StatusCode
,
body
)
}
else
{
return
""
,
fmt
.
Errorf
(
"%d"
,
response
.
StatusCode
)
}
}
signedData
,
err
:=
signer
.
Sign
(
nil
,
s
.
Bytes
())
if
err
!=
nil
{
var
token
api
.
TokenResponse
if
err
:=
json
.
Unmarshal
(
body
,
&
token
);
err
!=
nil
{
return
""
,
err
}
// signature is <pubkey>:<signature>
sig
:=
fmt
.
Sprintf
(
"%s:%s"
,
bytes
.
TrimSpace
(
parts
[
1
]),
base64
.
StdEncoding
.
EncodeToString
(
signedData
.
Blob
))
return
sig
,
nil
return
token
.
Token
,
nil
}
server/download.go
View file @
a468ae04
...
...
@@ -85,7 +85,7 @@ func (p *blobDownloadPart) Write(b []byte) (n int, err error) {
return
n
,
nil
}
func
(
b
*
blobDownload
)
Prepare
(
ctx
context
.
Context
,
requestURL
*
url
.
URL
,
opts
*
R
egistryOptions
)
error
{
func
(
b
*
blobDownload
)
Prepare
(
ctx
context
.
Context
,
requestURL
*
url
.
URL
,
opts
*
r
egistryOptions
)
error
{
partFilePaths
,
err
:=
filepath
.
Glob
(
b
.
Name
+
"-partial-*"
)
if
err
!=
nil
{
return
err
...
...
@@ -137,11 +137,11 @@ func (b *blobDownload) Prepare(ctx context.Context, requestURL *url.URL, opts *R
return
nil
}
func
(
b
*
blobDownload
)
Run
(
ctx
context
.
Context
,
requestURL
*
url
.
URL
,
opts
*
R
egistryOptions
)
{
func
(
b
*
blobDownload
)
Run
(
ctx
context
.
Context
,
requestURL
*
url
.
URL
,
opts
*
r
egistryOptions
)
{
b
.
err
=
b
.
run
(
ctx
,
requestURL
,
opts
)
}
func
(
b
*
blobDownload
)
run
(
ctx
context
.
Context
,
requestURL
*
url
.
URL
,
opts
*
R
egistryOptions
)
error
{
func
(
b
*
blobDownload
)
run
(
ctx
context
.
Context
,
requestURL
*
url
.
URL
,
opts
*
r
egistryOptions
)
error
{
defer
blobDownloadManager
.
Delete
(
b
.
Digest
)
ctx
,
b
.
CancelFunc
=
context
.
WithCancel
(
ctx
)
...
...
@@ -210,7 +210,7 @@ func (b *blobDownload) run(ctx context.Context, requestURL *url.URL, opts *Regis
return
nil
}
func
(
b
*
blobDownload
)
downloadChunk
(
ctx
context
.
Context
,
requestURL
*
url
.
URL
,
w
io
.
Writer
,
part
*
blobDownloadPart
,
opts
*
R
egistryOptions
)
error
{
func
(
b
*
blobDownload
)
downloadChunk
(
ctx
context
.
Context
,
requestURL
*
url
.
URL
,
w
io
.
Writer
,
part
*
blobDownloadPart
,
opts
*
r
egistryOptions
)
error
{
g
,
ctx
:=
errgroup
.
WithContext
(
ctx
)
g
.
Go
(
func
()
error
{
headers
:=
make
(
http
.
Header
)
...
...
@@ -334,7 +334,7 @@ func (b *blobDownload) Wait(ctx context.Context, fn func(api.ProgressResponse))
type
downloadOpts
struct
{
mp
ModelPath
digest
string
regOpts
*
R
egistryOptions
regOpts
*
r
egistryOptions
fn
func
(
api
.
ProgressResponse
)
}
...
...
server/images.go
View file @
a468ae04
...
...
@@ -28,7 +28,7 @@ import (
"github.com/jmorganca/ollama/version"
)
type
R
egistryOptions
struct
{
type
r
egistryOptions
struct
{
Insecure
bool
Username
string
Password
string
...
...
@@ -320,7 +320,7 @@ func CreateModel(ctx context.Context, name, modelFileDir string, commands []pars
switch
{
case
errors
.
Is
(
err
,
os
.
ErrNotExist
)
:
fn
(
api
.
ProgressResponse
{
Status
:
"pulling model"
})
if
err
:=
PullModel
(
ctx
,
c
.
Args
,
&
R
egistryOptions
{},
fn
);
err
!=
nil
{
if
err
:=
PullModel
(
ctx
,
c
.
Args
,
&
r
egistryOptions
{},
fn
);
err
!=
nil
{
return
err
}
...
...
@@ -840,7 +840,7 @@ PARAMETER {{ $k }} {{ printf "%#v" $parameter }}
return
buf
.
String
(),
nil
}
func
PushModel
(
ctx
context
.
Context
,
name
string
,
regOpts
*
R
egistryOptions
,
fn
func
(
api
.
ProgressResponse
))
error
{
func
PushModel
(
ctx
context
.
Context
,
name
string
,
regOpts
*
r
egistryOptions
,
fn
func
(
api
.
ProgressResponse
))
error
{
mp
:=
ParseModelPath
(
name
)
fn
(
api
.
ProgressResponse
{
Status
:
"retrieving manifest"
})
...
...
@@ -890,7 +890,7 @@ func PushModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
return
nil
}
func
PullModel
(
ctx
context
.
Context
,
name
string
,
regOpts
*
R
egistryOptions
,
fn
func
(
api
.
ProgressResponse
))
error
{
func
PullModel
(
ctx
context
.
Context
,
name
string
,
regOpts
*
r
egistryOptions
,
fn
func
(
api
.
ProgressResponse
))
error
{
mp
:=
ParseModelPath
(
name
)
var
manifest
*
ManifestV2
...
...
@@ -996,7 +996,7 @@ func PullModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
return
nil
}
func
pullModelManifest
(
ctx
context
.
Context
,
mp
ModelPath
,
regOpts
*
R
egistryOptions
)
(
*
ManifestV2
,
error
)
{
func
pullModelManifest
(
ctx
context
.
Context
,
mp
ModelPath
,
regOpts
*
r
egistryOptions
)
(
*
ManifestV2
,
error
)
{
requestURL
:=
mp
.
BaseURL
()
.
JoinPath
(
"v2"
,
mp
.
GetNamespaceRepository
(),
"manifests"
,
mp
.
Tag
)
headers
:=
make
(
http
.
Header
)
...
...
@@ -1028,7 +1028,7 @@ func GetSHA256Digest(r io.Reader) (string, int64) {
var
errUnauthorized
=
fmt
.
Errorf
(
"unauthorized"
)
func
makeRequestWithRetry
(
ctx
context
.
Context
,
method
string
,
requestURL
*
url
.
URL
,
headers
http
.
Header
,
body
io
.
ReadSeeker
,
regOpts
*
R
egistryOptions
)
(
*
http
.
Response
,
error
)
{
func
makeRequestWithRetry
(
ctx
context
.
Context
,
method
string
,
requestURL
*
url
.
URL
,
headers
http
.
Header
,
body
io
.
ReadSeeker
,
regOpts
*
r
egistryOptions
)
(
*
http
.
Response
,
error
)
{
for
i
:=
0
;
i
<
2
;
i
++
{
resp
,
err
:=
makeRequest
(
ctx
,
method
,
requestURL
,
headers
,
body
,
regOpts
)
if
err
!=
nil
{
...
...
@@ -1042,9 +1042,8 @@ func makeRequestWithRetry(ctx context.Context, method string, requestURL *url.UR
switch
{
case
resp
.
StatusCode
==
http
.
StatusUnauthorized
:
// Handle authentication error with one retry
auth
:=
resp
.
Header
.
Get
(
"www-authenticate"
)
authRedir
:=
ParseAuthRedirectString
(
auth
)
token
,
err
:=
getAuthToken
(
ctx
,
authRedir
)
challenge
:=
parseRegistryChallenge
(
resp
.
Header
.
Get
(
"www-authenticate"
))
token
,
err
:=
getAuthorizationToken
(
ctx
,
challenge
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -1071,7 +1070,7 @@ func makeRequestWithRetry(ctx context.Context, method string, requestURL *url.UR
return
nil
,
errUnauthorized
}
func
makeRequest
(
ctx
context
.
Context
,
method
string
,
requestURL
*
url
.
URL
,
headers
http
.
Header
,
body
io
.
Reader
,
regOpts
*
R
egistryOptions
)
(
*
http
.
Response
,
error
)
{
func
makeRequest
(
ctx
context
.
Context
,
method
string
,
requestURL
*
url
.
URL
,
headers
http
.
Header
,
body
io
.
Reader
,
regOpts
*
r
egistryOptions
)
(
*
http
.
Response
,
error
)
{
if
requestURL
.
Scheme
!=
"http"
&&
regOpts
!=
nil
&&
regOpts
.
Insecure
{
requestURL
.
Scheme
=
"http"
}
...
...
@@ -1146,10 +1145,10 @@ func getValue(header, key string) string {
return
header
[
startIdx
:
endIdx
]
}
func
P
arse
AuthRedirectStri
ng
(
authStr
string
)
AuthRedirect
{
func
p
arse
RegistryChalle
ng
e
(
authStr
string
)
registryChallenge
{
authStr
=
strings
.
TrimPrefix
(
authStr
,
"Bearer "
)
return
AuthRedirect
{
return
registryChallenge
{
Realm
:
getValue
(
authStr
,
"realm"
),
Service
:
getValue
(
authStr
,
"service"
),
Scope
:
getValue
(
authStr
,
"scope"
),
...
...
server/routes.go
View file @
a468ae04
...
...
@@ -479,7 +479,7 @@ func PullModelHandler(c *gin.Context) {
ch
<-
r
}
regOpts
:=
&
R
egistryOptions
{
regOpts
:=
&
r
egistryOptions
{
Insecure
:
req
.
Insecure
,
}
...
...
@@ -528,7 +528,7 @@ func PushModelHandler(c *gin.Context) {
ch
<-
r
}
regOpts
:=
&
R
egistryOptions
{
regOpts
:=
&
r
egistryOptions
{
Insecure
:
req
.
Insecure
,
}
...
...
server/upload.go
View file @
a468ae04
...
...
@@ -49,7 +49,7 @@ const (
maxUploadPartSize
int64
=
1000
*
format
.
MegaByte
)
func
(
b
*
blobUpload
)
Prepare
(
ctx
context
.
Context
,
requestURL
*
url
.
URL
,
opts
*
R
egistryOptions
)
error
{
func
(
b
*
blobUpload
)
Prepare
(
ctx
context
.
Context
,
requestURL
*
url
.
URL
,
opts
*
r
egistryOptions
)
error
{
p
,
err
:=
GetBlobsPath
(
b
.
Digest
)
if
err
!=
nil
{
return
err
...
...
@@ -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
// 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
*
R
egistryOptions
)
{
func
(
b
*
blobUpload
)
Run
(
ctx
context
.
Context
,
opts
*
r
egistryOptions
)
{
defer
blobUploadManager
.
Delete
(
b
.
Digest
)
ctx
,
b
.
CancelFunc
=
context
.
WithCancel
(
ctx
)
...
...
@@ -212,7 +212,7 @@ func (b *blobUpload) Run(ctx context.Context, opts *RegistryOptions) {
b
.
done
=
true
}
func
(
b
*
blobUpload
)
uploadPart
(
ctx
context
.
Context
,
method
string
,
requestURL
*
url
.
URL
,
part
*
blobUploadPart
,
opts
*
R
egistryOptions
)
error
{
func
(
b
*
blobUpload
)
uploadPart
(
ctx
context
.
Context
,
method
string
,
requestURL
*
url
.
URL
,
part
*
blobUploadPart
,
opts
*
r
egistryOptions
)
error
{
headers
:=
make
(
http
.
Header
)
headers
.
Set
(
"Content-Type"
,
"application/octet-stream"
)
headers
.
Set
(
"Content-Length"
,
fmt
.
Sprintf
(
"%d"
,
part
.
Size
))
...
...
@@ -277,9 +277,8 @@ func (b *blobUpload) uploadPart(ctx context.Context, method string, requestURL *
case
resp
.
StatusCode
==
http
.
StatusUnauthorized
:
w
.
Rollback
()
auth
:=
resp
.
Header
.
Get
(
"www-authenticate"
)
authRedir
:=
ParseAuthRedirectString
(
auth
)
token
,
err
:=
getAuthToken
(
ctx
,
authRedir
)
challenge
:=
parseRegistryChallenge
(
resp
.
Header
.
Get
(
"www-authenticate"
))
token
,
err
:=
getAuthorizationToken
(
ctx
,
challenge
)
if
err
!=
nil
{
return
err
}
...
...
@@ -364,7 +363,7 @@ func (p *progressWriter) Rollback() {
p
.
written
=
0
}
func
uploadBlob
(
ctx
context
.
Context
,
mp
ModelPath
,
layer
*
Layer
,
opts
*
R
egistryOptions
,
fn
func
(
api
.
ProgressResponse
))
error
{
func
uploadBlob
(
ctx
context
.
Context
,
mp
ModelPath
,
layer
*
Layer
,
opts
*
r
egistryOptions
,
fn
func
(
api
.
ProgressResponse
))
error
{
requestURL
:=
mp
.
BaseURL
()
requestURL
=
requestURL
.
JoinPath
(
"v2"
,
mp
.
GetNamespaceRepository
(),
"blobs"
,
layer
.
Digest
)
...
...
Prev
1
2
3
4
5
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment