@@ -26,6 +26,7 @@ type Client struct {
2626 transport http.RoundTripper
2727 userAgent string
2828 keychain authn.Keychain
29+ auth authn.Authenticator
2930}
3031
3132type ClientOption func (* Client )
@@ -46,6 +47,17 @@ func WithUserAgent(userAgent string) ClientOption {
4647 }
4748}
4849
50+ func WithAuthConfig (username , password string ) ClientOption {
51+ return func (c * Client ) {
52+ if username != "" && password != "" {
53+ c .auth = & authn.Basic {
54+ Username : username ,
55+ Password : password ,
56+ }
57+ }
58+ }
59+ }
60+
4961func NewClient (opts ... ClientOption ) * Client {
5062 client := & Client {
5163 transport : remote .DefaultTransport ,
@@ -65,13 +77,22 @@ func (c *Client) Model(ctx context.Context, reference string) (types.ModelArtifa
6577 return nil , NewReferenceError (reference , err )
6678 }
6779
68- // Return the artifact at the given reference
69- remoteImg , err := remote .Image ( ref ,
80+ // Set up authentication options
81+ authOpts := [] remote.Option {
7082 remote .WithContext (ctx ),
71- remote .WithAuthFromKeychain (c .keychain ),
7283 remote .WithTransport (c .transport ),
7384 remote .WithUserAgent (c .userAgent ),
74- )
85+ }
86+
87+ // Use direct auth if provided, otherwise fall back to keychain
88+ if c .auth != nil {
89+ authOpts = append (authOpts , remote .WithAuth (c .auth ))
90+ } else {
91+ authOpts = append (authOpts , remote .WithAuthFromKeychain (c .keychain ))
92+ }
93+
94+ // Return the artifact at the given reference
95+ remoteImg , err := remote .Image (ref , authOpts ... )
7596 if err != nil {
7697 errStr := err .Error ()
7798 if strings .Contains (errStr , "UNAUTHORIZED" ) {
@@ -93,6 +114,7 @@ type Target struct {
93114 transport http.RoundTripper
94115 userAgent string
95116 keychain authn.Keychain
117+ auth authn.Authenticator
96118}
97119
98120func (c * Client ) NewTarget (tag string ) (* Target , error ) {
@@ -105,20 +127,30 @@ func (c *Client) NewTarget(tag string) (*Target, error) {
105127 transport : c .transport ,
106128 userAgent : c .userAgent ,
107129 keychain : c .keychain ,
130+ auth : c .auth ,
108131 }, nil
109132}
110133
111134func (t * Target ) Write (ctx context.Context , model types.ModelArtifact , progressWriter io.Writer ) error {
112135 pr := progress .NewProgressReporter (progressWriter , progress .PushMsg , nil )
113136 defer pr .Wait ()
114137
115- if err := remote .Write (t .reference , model ,
138+ // Set up authentication options
139+ authOpts := []remote.Option {
116140 remote .WithContext (ctx ),
117- remote .WithAuthFromKeychain (t .keychain ),
118141 remote .WithTransport (t .transport ),
119142 remote .WithUserAgent (t .userAgent ),
120143 remote .WithProgress (pr .Updates ()),
121- ); err != nil {
144+ }
145+
146+ // Use direct auth if provided, otherwise fall back to keychain
147+ if t .auth != nil {
148+ authOpts = append (authOpts , remote .WithAuth (t .auth ))
149+ } else {
150+ authOpts = append (authOpts , remote .WithAuthFromKeychain (t .keychain ))
151+ }
152+
153+ if err := remote .Write (t .reference , model , authOpts ... ); err != nil {
122154 return fmt .Errorf ("write to registry %q: %w" , t .reference .String (), err )
123155 }
124156 return nil
0 commit comments