func Open(info *Info, opts DialOpts) (Connection, error) {
	if err := info.Validate(); err != nil {
		return nil, errors.Annotate(err, "validating info for opening an API connection")
	}
	if opts.Clock == nil {
		opts.Clock = clock.WallClock
	}
	ctx := context.Background()
	dialCtx := ctx
	if opts.Timeout > 0 {
		ctx1, cancel := utils.ContextWithTimeout(dialCtx, opts.Clock, opts.Timeout)
		defer cancel()
		dialCtx = ctx1
	}

	dialResult, err := dialAPI(dialCtx, info, opts)
	if err != nil {
		return nil, errors.Trace(err)
	}

	client := rpc.NewConn(jsoncodec.New(dialResult.conn), nil)
	client.Start(ctx)

	bakeryClient := opts.BakeryClient
	if bakeryClient == nil {
		bakeryClient = httpbakery.NewClient()
	} else {
		// Make a copy of the bakery client and its HTTP client
		c := *opts.BakeryClient
		bakeryClient = &c
		httpc := *bakeryClient.Client
		bakeryClient.Client = &httpc
	}

	// Technically when there's no CACert, we don't need this
	// machinery, because we could just use http.DefaultTransport
	// for everything, but it's easier just to leave it in place.
	bakeryClient.Client.Transport = &hostSwitchingTransport{
		primaryHost: dialResult.addr,
		primary: jujuhttp.NewHTTPTLSTransport(jujuhttp.TransportConfig{
			TLSConfig: dialResult.tlsConfig,
		}),
		fallback: http.DefaultTransport,
	}

	host := PerferredHost(info)
	if host == "" {
		host = dialResult.addr
	}

	st := &state{
		ctx:                 context.Background(),
		client:              client,
		conn:                dialResult.conn,
		clock:               opts.Clock,
		addr:                dialResult.addr,
		ipAddr:              dialResult.ipAddr,
		cookieURL:           CookieURLFromHost(host),
		pingerFacadeVersion: facadeVersions["Pinger"],
		serverScheme:        "https",
		serverRootAddress:   dialResult.addr,
		// We populate the username and password before
		// login because, when doing HTTP requests, we'll want
		// to use the same username and password for authenticating
		// those. If login fails, we discard the connection.
		tag:          tagToString(info.Tag),
		password:     info.Password,
		macaroons:    info.Macaroons,
		nonce:        info.Nonce,
		tlsConfig:    dialResult.tlsConfig,
		bakeryClient: bakeryClient,
		modelTag:     info.ModelTag,
		proxier:      dialResult.proxier,
	}
	if !info.SkipLogin {
		if err := loginWithContext(dialCtx, st, info); err != nil {
			dialResult.conn.Close()
			return nil, errors.Trace(err)
		}
	}

	st.broken = make(chan struct{})
	st.closed = make(chan struct{})

	go (&monitor{
		clock:       opts.Clock,
		ping:        st.Ping,
		pingPeriod:  PingPeriod,
		pingTimeout: pingTimeout,
		closed:      st.closed,
		dead:        client.Dead(),
		broken:      st.broken,
	}).run()
	return st, nil
}
// Open establishes a connection to the API server using the Info
// given, returning a State instance which can be used to make API
// requests.
//
// If the model is hosted on a different server, Open
// will return an error with a *RedirectError cause
// holding the details of another server to connect to.
//
// See Connect for details of the connection mechanics.
Open establishes a connection to the API server using the Info
given, returning a State instance which can be used to make API
requests.

If the model is hosted on a different server, Open
will return an error with a *RedirectError cause
holding the details of another server to connect to.

See Connect for details of the connection mechanics.
// Open establishes a connection to the API server using the Info // given returning a State instance which can be used to make API // requests . // // If the model is hosted on a different server Open // will return an error with a * RedirectError cause // holding the details of another server to connect to . // // See Connect for details of the connection mechanics .
func Open(info *Info, opts DialOpts) (Connection, error) {
	if err := info.Validate(); err != nil {
		return nil, errors.Annotate(err, "validating info for opening an API connection")
	}
	if opts.Clock == nil {
		opts.Clock = clock.WallClock
	}
	ctx := context.Background()
	dialCtx := ctx
	if opts.Timeout > 0 {
		ctx1, cancel := utils.ContextWithTimeout(dialCtx, opts.Clock, opts.Timeout)
		defer cancel()
		dialCtx = ctx1
	}
	dialResult, err := dialAPI(dialCtx, info, opts)
	if err != nil {
		return nil, errors.Trace(err)
	}
	client := rpc.NewConn(jsoncodec.New(dialResult.conn), nil)
	client.Start(ctx)
	bakeryClient := opts.BakeryClient
	if bakeryClient == nil {
		bakeryClient = httpbakery.NewClient()
	} else {
		c := *opts.BakeryClient
		bakeryClient = &c
		httpc := *bakeryClient.Client
		bakeryClient.Client = &httpc
	}
	bakeryClient.Client.Transport = &hostSwitchingTransport{
		primaryHost: dialResult.addr,
		primary: jujuhttp.NewHTTPTLSTransport(jujuhttp.TransportConfig{
			TLSConfig: dialResult.tlsConfig,
		}),
		fallback: http.DefaultTransport,
	}
	host := PerferredHost(info)
	if host == "" {
		host = dialResult.addr
	}
	st := &state{
		ctx:                 context.Background(),
		client:              client,
		conn:                dialResult.conn,
		clock:               opts.Clock,
		addr:                dialResult.addr,
		ipAddr:              dialResult.ipAddr,
		cookieURL:           CookieURLFromHost(host),
		pingerFacadeVersion: facadeVersions["Pinger"],
		serverScheme:        "https",
		serverRootAddress:   dialResult.addr,
		tag:          tagToString(info.Tag),
		password:     info.Password,
		macaroons:    info.Macaroons,
		nonce:        info.Nonce,
		tlsConfig:    dialResult.tlsConfig,
		bakeryClient: bakeryClient,
		modelTag:     info.ModelTag,
		proxier:      dialResult.proxier,
	}
	if !info.SkipLogin {
		if err := loginWithContext(dialCtx, st, info); err != nil {
			dialResult.conn.Close()
			return nil, errors.Trace(err)
		}
	}
	st.broken = make(chan struct{})
	st.closed = make(chan struct{})
	go (&monitor{
		clock:       opts.Clock,
		ping:        st.Ping,
		pingPeriod:  PingPeriod,
		pingTimeout: pingTimeout,
		closed:      st.closed,
		dead:        client.Dead(),
		broken:      st.broken,
	}).run()
	return st, nil
}
func Open ( info * Info , opts DialOpts ) ( Connection , error ) { if err := info . Validate ( ) ; err != nil { return nil , errors . Annotate ( err , " " ) } if opts . Clock == nil { opts . Clock = clock . WallClock } ctx := context . Background ( ) dialCtx := ctx if opts . Timeout > 0 { ctx1 , cancel := utils . ContextWithTimeout ( dialCtx , opts . Clock , opts . Timeout ) defer cancel ( ) dialCtx = ctx1 } dialResult , err := dialAPI ( dialCtx , info , opts ) if err != nil { return nil , errors . Trace ( err ) } client := rpc . NewConn ( jsoncodec . New ( dialResult . conn ) , nil ) client . Start ( ctx ) bakeryClient := opts . BakeryClient if bakeryClient == nil { bakeryClient = httpbakery . NewClient ( ) } else { c := * opts . BakeryClient bakeryClient = & c httpc := * bakeryClient . Client bakeryClient . Client = & httpc } bakeryClient . Client . Transport = & hostSwitchingTransport { primaryHost : dialResult . addr , primary : jujuhttp . NewHTTPTLSTransport ( jujuhttp . TransportConfig { TLSConfig : dialResult . tlsConfig , } ) , fallback : http . DefaultTransport , } host := PerferredHost ( info ) if host == " " { host = dialResult . addr } st := & state { ctx : context . Background ( ) , client : client , conn : dialResult . conn , clock : opts . Clock , addr : dialResult . addr , ipAddr : dialResult . ipAddr , cookieURL : CookieURLFromHost ( host ) , pingerFacadeVersion : facadeVersions [ " " ] , serverScheme : " " , serverRootAddress : dialResult . addr , tag : tagToString ( info . Tag ) , password : info . Password , macaroons : info . Macaroons , nonce : info . Nonce , tlsConfig : dialResult . tlsConfig , bakeryClient : bakeryClient , modelTag : info . ModelTag , proxier : dialResult . proxier , } if ! info . SkipLogin { if err := loginWithContext ( dialCtx , st , info ) ; err != nil { dialResult . conn . Close ( ) return nil , errors . Trace ( err ) } } st . broken = make ( chan struct { } ) st . closed = make ( chan struct { } ) go ( & monitor { clock : opts . Clock , ping : st . Ping , pingPeriod : PingPeriod , pingTimeout : pingTimeout , closed : st . closed , dead : client . Dead ( ) , broken : st . broken , } ) . run ( ) return st , nil }
Open establishes a connection to the API server using the Info
given, returning a State instance which can be used to make API
requests.
Open establishes a connection to the API server using the Info given returning a State instance which can be used to make API requests .
// Make a copy of the bakery client and its HTTP client // Technically when there's no CACert, we don't need this // machinery, because we could just use http.DefaultTransport // for everything, but it's easier just to leave it in place. // We populate the username and password before // login because, when doing HTTP requests, we'll want // to use the same username and password for authenticating // those. If login fails, we discard the connection.