openAndMigrate opens a connection and migrates it.
(ctx context.Context, cfg cachedConnectionConfig)
| 92 | |
| 93 | // openAndMigrate opens a connection and migrates it. |
| 94 | func (r *Runtime) openAndMigrate(ctx context.Context, cfg cachedConnectionConfig) (drivers.Handle, error) { |
| 95 | logger := r.Logger |
| 96 | activityClient := r.activity |
| 97 | if cfg.instanceID != "" { // Not shared across multiple instances |
| 98 | inst, err := r.Instance(ctx, cfg.instanceID) |
| 99 | if err != nil { |
| 100 | return nil, err |
| 101 | } |
| 102 | |
| 103 | logger, err = r.InstanceLogger(ctx, cfg.instanceID) |
| 104 | if err != nil { |
| 105 | return nil, err |
| 106 | } |
| 107 | |
| 108 | activityDims := instanceAnnotationsToAttribs(inst) |
| 109 | if cfg.provision { |
| 110 | activityDims = append(activityDims, attribute.Bool("managed", true)) |
| 111 | } |
| 112 | if activityClient != nil { |
| 113 | activityClient = activityClient.With(activityDims...) |
| 114 | } |
| 115 | |
| 116 | if cfg.provision { |
| 117 | if cfg.name == inst.AdminConnector { |
| 118 | return nil, fmt.Errorf("cannot provision the admin connector (catch-22)") |
| 119 | } |
| 120 | |
| 121 | // Give the driver a hint that it's a managed connector. |
| 122 | cfg.config = maps.Clone(cfg.config) |
| 123 | cfg.config["managed"] = true |
| 124 | |
| 125 | // As a special carve-out, we never try to provision DuckDB through the admin service. |
| 126 | // (Since the driver just starts an embedded DuckDB when `managed: true`.) |
| 127 | selfProvision := cfg.driver == "duckdb" |
| 128 | if !selfProvision { |
| 129 | // Provision the connector using the admin connector. |
| 130 | admin, release, err := r.Admin(ctx, cfg.instanceID) |
| 131 | if err != nil { |
| 132 | return nil, fmt.Errorf("failed to get admin client: %w", err) |
| 133 | } |
| 134 | defer release() |
| 135 | |
| 136 | newConfig, err := admin.ProvisionConnector(ctx, cfg.name, cfg.driver, cfg.provisionArgs) |
| 137 | if err != nil { |
| 138 | if !errors.Is(err, drivers.ErrNotImplemented) { |
| 139 | return nil, fmt.Errorf("failed to provision %q: %w", cfg.name, err) |
| 140 | } |
| 141 | // As a fallback, we pass the provision arguments to the driver, giving it a chance to provision itself if it supports it. |
| 142 | selfProvision = true |
| 143 | } |
| 144 | if !selfProvision { |
| 145 | // Success |
| 146 | // Merge the new provisioned config with the existing one. |
| 147 | for key, value := range newConfig { |
| 148 | cfg.config[key] = value |
| 149 | } |
| 150 | } |
| 151 | } |
no test coverage detected