diff --git a/go/libraries/doltcore/remotesrv/server.go b/go/libraries/doltcore/remotesrv/server.go index b3d5b37eca..ccfa9c7950 100644 --- a/go/libraries/doltcore/remotesrv/server.go +++ b/go/libraries/doltcore/remotesrv/server.go @@ -69,6 +69,10 @@ type ServerArgs struct { // listeners. The scheme used in the URLs returned from the gRPC server // will be https. TLSConfig *tls.Config + + // In the cluster context, we want to create the databases automatically when pushed to. Other contexts we want to + // error when the user pushes to a database that doesn't exist. + CreateUnknownDatabases bool } func NewServer(args ServerArgs) (*Server, error) { diff --git a/go/libraries/doltcore/sqle/cluster/controller.go b/go/libraries/doltcore/sqle/cluster/controller.go index f90a80998b..f654896a9b 100644 --- a/go/libraries/doltcore/sqle/cluster/controller.go +++ b/go/libraries/doltcore/sqle/cluster/controller.go @@ -688,6 +688,7 @@ func (c *Controller) RemoteSrvServerArgs(ctxFactory func(context.Context) (*sql. if err != nil { return remotesrv.ServerArgs{}, err } + args.CreateUnknownDatabases = true args.DBCache = remotesrvStoreCache{args.DBCache, c} c.remoteSrvDBCache = args.DBCache diff --git a/go/libraries/doltcore/sqle/remotesrv.go b/go/libraries/doltcore/sqle/remotesrv.go index b63ceb9dca..6c46510f11 100644 --- a/go/libraries/doltcore/sqle/remotesrv.go +++ b/go/libraries/doltcore/sqle/remotesrv.go @@ -28,6 +28,7 @@ import ( type remotesrvStore struct { ctxFactory func(context.Context) (*sql.Context, error) readonly bool + createDBs bool } var _ remotesrv.DBCache = remotesrvStore{} @@ -40,7 +41,7 @@ func (s remotesrvStore) Get(ctx context.Context, path, nbfVerStr string) (remote sess := dsess.DSessFromSess(sqlCtx.Session) db, err := sess.Provider().Database(sqlCtx, path) if err != nil { - if !s.readonly && sql.ErrDatabaseNotFound.Is(err) { + if !s.readonly && sql.ErrDatabaseNotFound.Is(err) && s.createDBs { err = sess.Provider().CreateDatabase(sqlCtx, path) if err != nil { return nil, err @@ -74,7 +75,7 @@ func RemoteSrvServerArgs(ctxFactory func(context.Context) (*sql.Context, error), } sess := dsess.DSessFromSess(sqlCtx.Session) args.FS = sess.Provider().FileSystem() - args.DBCache = remotesrvStore{ctxFactory, args.ReadOnly} + args.DBCache = remotesrvStore{ctxFactory, args.ReadOnly, args.CreateUnknownDatabases} return args, nil } diff --git a/integration-tests/bats/sql-server-remotesrv.bats b/integration-tests/bats/sql-server-remotesrv.bats index f121d4305e..8c2bf5b0dc 100644 --- a/integration-tests/bats/sql-server-remotesrv.bats +++ b/integration-tests/bats/sql-server-remotesrv.bats @@ -535,3 +535,100 @@ GRANT CLONE_ADMIN ON *.* TO clone_admin_user@'localhost'; [[ "$status" -ne 0 ]] || false [[ "$output" =~ "this server only provides read-only access" ]] || false } + +@test "sql-server-remotesrv: delete remote branch from remotesapi port as super user" { + mkdir remote + cd remote + dolt init + dolt sql -q 'create table names (name varchar(10) primary key);' + dolt sql -q 'insert into names (name) values ("abe"), ("betsy"), ("calvin");' + dolt add names + dolt commit -m 'initial names.' + dolt branch new_branch HEAD + + APIPORT=$( definePORT ) + export DOLT_REMOTE_PASSWORD="rootpass" + export SQL_USER="root" + start_sql_server_with_args -u "$SQL_USER" -p "$DOLT_REMOTE_PASSWORD" --remotesapi-port $APIPORT + + cd ../ + dolt clone http://localhost:$APIPORT/remote cloned_db -u $SQL_USER + cd cloned_db + + run dolt push origin --user $SQL_USER :new_branch + [[ "$status" -eq 0 ]] || false + + # TODO - verify output. Currently we always print "new branch" + # To https://doltremoteapi.dolthub.com/dolthub/macneale-remote-test + # * [new branch] HEAD -> main + # [[ "$output" =~ "[deleted] new_branch" ]] || false + + cd ../remote + run dolt branch -a + ! [[ "$output" =~ "new_branch" ]] || false + [[ "$output" =~ "main" ]] || false +} + +@test "sql-server-remotesrv: delete remote dirty branch from remotesapi requires force" { + mkdir remote + cd remote + dolt init + dolt sql -q 'create table names (name varchar(10) primary key);' + dolt sql -q 'insert into names (name) values ("abe"), ("betsy"), ("calvin");' + dolt add names + dolt commit -m 'initial names.' + dolt checkout -b new_branch HEAD + dolt sql -q 'insert into names (name) values ("zeek");' # dirty the workspace + dolt checkout main + + APIPORT=$(definePORT) + export DOLT_REMOTE_PASSWORD="rootpass" + export SQL_USER="root" + start_sql_server_with_args -u "$SQL_USER" -p "$DOLT_REMOTE_PASSWORD" --remotesapi-port $APIPORT + + cd ../ + dolt clone http://localhost:$APIPORT/remote cloned_db -u $SQL_USER + cd cloned_db + + run dolt push origin --force --user $SQL_USER :new_branch + [[ "$status" -eq 0 ]] || false + + # TODO - verify output. Currently we always print "new branch" + # To https://doltremoteapi.dolthub.com/dolthub/macneale-remote-test + # * [new branch] HEAD -> main + # [[ "$output" =~ "[deleted] new_branch" ]] || false + + cd ../remote + run dolt branch -a + ! [[ "$output" =~ "new_branch" ]] || false + [[ "$output" =~ "main" ]] || false +} + +@test "sql-server-remotesrv: push to non-existent database fails" { + mkdir remote + cd remote + dolt init + dolt sql -q 'create table names (name varchar(10) primary key);' + dolt sql -q 'insert into names (name) values ("abe"), ("betsy"), ("calvin");' + dolt add names + dolt commit -m 'initial names.' + + APIPORT=$(definePORT) + export DOLT_REMOTE_PASSWORD="rootpass" + export SQL_USER="root" + start_sql_server_with_args -u "$SQL_USER" -p "$DOLT_REMOTE_PASSWORD" --remotesapi-port $APIPORT + + cd ../ + dolt clone http://localhost:$APIPORT/remote cloned_db -u $SQL_USER + cd cloned_db + + dolt remote add nodb http://localhost:$APIPORT/nodb + + run dolt push nodb --user $SQL_USER main:new_branch + [[ "$status" -ne 0 ]] || false + [[ "$output" =~ "database not found: nodb" ]] || false # NM4 + + run dolt push --force nodb --user $SQL_USER main:new_branch + [[ "$status" -ne 0 ]] || false + [[ "$output" =~ "database not found: nodb" ]] || false # NM4 +}