Skip to content

Commit bd1ea9f

Browse files
committed
Added local file access
1 parent 079a9ca commit bd1ea9f

File tree

11 files changed

+405
-171
lines changed

11 files changed

+405
-171
lines changed

cmd/modern/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ func (c *Root) SubCommands() []cmdparser.Command {
6767
cmdparser.New[*root.Query](dependencies),
6868
cmdparser.New[*root.Start](dependencies),
6969
cmdparser.New[*root.Stop](dependencies),
70+
cmdparser.New[*root.System](dependencies),
7071
cmdparser.New[*root.Uninstall](dependencies),
7172
cmdparser.New[*root.Use](dependencies),
7273
}

cmd/modern/root/install/mssql-base.go

Lines changed: 16 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ import (
99
"fmt"
1010
"github.com/microsoft/go-sqlcmd/internal/cmdparser/dependency"
1111
"github.com/microsoft/go-sqlcmd/internal/tools"
12-
"net/url"
1312
"os"
14-
"path/filepath"
1513
"runtime"
1614
"strings"
1715

@@ -23,7 +21,6 @@ import (
2321
"github.com/microsoft/go-sqlcmd/internal/cmdparser"
2422
"github.com/microsoft/go-sqlcmd/internal/config"
2523
"github.com/microsoft/go-sqlcmd/internal/container"
26-
"github.com/microsoft/go-sqlcmd/internal/http"
2724
"github.com/microsoft/go-sqlcmd/internal/output"
2825
"github.com/microsoft/go-sqlcmd/internal/pal"
2926
"github.com/microsoft/go-sqlcmd/internal/secret"
@@ -298,7 +295,7 @@ func (c *MssqlBase) createContainer(imageName string, contextName string) {
298295

299296
// Do an early exit if url doesn't exist
300297
if c.usingDatabaseUrl != "" {
301-
c.validateUsingUrlExists()
298+
mssqlcontainer.ValidateUsingUrlExists(c.usingDatabaseUrl, output)
302299
}
303300

304301
if c.defaultDatabase != "" {
@@ -382,7 +379,15 @@ func (c *MssqlBase) createContainer(imageName string, contextName string) {
382379

383380
// Download and restore DB if asked
384381
if c.usingDatabaseUrl != "" {
385-
c.downloadAndRestoreDb(controller, containerId, userName, password)
382+
mssqlcontainer.DownloadAndRestoreDb(
383+
controller,
384+
containerId,
385+
c.usingDatabaseUrl,
386+
userName,
387+
password,
388+
c.sql.Query,
389+
c.Cmd.Output(),
390+
)
386391
}
387392

388393
if c.openTool == "" {
@@ -455,36 +460,6 @@ func (c *MssqlBase) createContainer(imageName string, contextName string) {
455460
if c.openFile != "" {
456461
args = append(args, c.openFile)
457462

458-
/*
459-
var k registry.Key
460-
prefix := "SOFTWARE\\Classes\\"
461-
urlScheme := "sqlcmd"
462-
basePath := prefix + urlScheme
463-
permission := uint32(registry.QUERY_VALUE | registry.SET_VALUE)
464-
baseKey := registry.CURRENT_USER
465-
466-
programLocation := "\"C:\\Windows\\notepad.exe\""
467-
468-
// create key
469-
registry.CreateKey(baseKey, basePath, permission)
470-
471-
// set description
472-
k.SetStringValue("", "Notepad app")
473-
k.SetStringValue("URL Protocol", "")
474-
475-
// set icon
476-
registry.CreateKey(registry.CURRENT_USER, "lumiere\\DefaultIcon", registry.ALL_ACCESS)
477-
k.SetStringValue("", programLocation+",1")
478-
479-
// create tree
480-
registry.CreateKey(baseKey, basePath+"\\shell", permission)
481-
registry.CreateKey(baseKey, basePath+"\\shell\\open", permission)
482-
registry.CreateKey(baseKey, basePath+"\\shell\\open\\command", permission)
483-
484-
// set open command
485-
k.SetStringValue("", programLocation+" \"%1\"")
486-
*/
487-
488463
a := os.Args[1:]
489464
data, _ := json.Marshal(&a)
490465

@@ -498,45 +473,6 @@ func (c *MssqlBase) createContainer(imageName string, contextName string) {
498473
}
499474
}
500475

501-
func (c *MssqlBase) validateUsingUrlExists() {
502-
output := c.Cmd.Output()
503-
databaseUrl := extractUrl(c.usingDatabaseUrl)
504-
u, err := url.Parse(databaseUrl)
505-
c.CheckErr(err)
506-
507-
if u.Scheme != "http" && u.Scheme != "https" {
508-
output.FatalfWithHints(
509-
[]string{
510-
"--using URL must be http or https",
511-
},
512-
"%q is not a valid URL for --using flag", c.usingDatabaseUrl)
513-
}
514-
515-
if u.Path == "" {
516-
output.FatalfWithHints(
517-
[]string{
518-
"--using URL must have a path to .bak, .bacpac or .mdf (.7z) file",
519-
},
520-
"%q is not a valid URL for --using flag", c.usingDatabaseUrl)
521-
}
522-
523-
_, f := filepath.Split(u.Path)
524-
if filepath.Ext(f) != ".bak" && filepath.Ext(f) != ".bacpac" && filepath.Ext(f) != ".mdf" && filepath.Ext(f) != ".7z" {
525-
output.FatalfWithHints(
526-
[]string{
527-
"--using file URL must be a .bak, .bacpac, or .mdf (.7z) file",
528-
},
529-
"Invalid --using file type, extension %q is not supported", filepath.Ext(f))
530-
}
531-
532-
// Verify the url actually exists, and early exit if it doesn't
533-
urlExists(databaseUrl, output)
534-
}
535-
536-
func (c *MssqlBase) query(commandText string) {
537-
c.sql.Query(commandText)
538-
}
539-
540476
// createNonSaUser creates a user (non-sa) and assigns the sysadmin role
541477
// to the user. It also creates a default database with the provided name
542478
// and assigns the default database to the user. Finally, it disables
@@ -554,7 +490,7 @@ func (c *MssqlBase) createNonSaUser(
554490

555491
// Create the default database, if it isn't a downloaded database
556492
output.Infof("Creating default database [%s]", defaultDatabase)
557-
c.query(fmt.Sprintf("CREATE DATABASE [%s]", defaultDatabase))
493+
c.sql.Query(fmt.Sprintf("CREATE DATABASE [%s]", defaultDatabase))
558494
}
559495

560496
const createLogin = `CREATE LOGIN [%s]
@@ -566,64 +502,21 @@ CHECK_POLICY=OFF`
566502
@loginame = N'%s',
567503
@rolename = N'sysadmin'`
568504

569-
c.query(fmt.Sprintf(createLogin, userName, password, defaultDatabase))
570-
c.query(fmt.Sprintf(addSrvRoleMember, userName))
505+
c.sql.Query(fmt.Sprintf(createLogin, userName, password, defaultDatabase))
506+
c.sql.Query(fmt.Sprintf(addSrvRoleMember, userName))
571507

572508
// Correct safety protocol is to rotate the sa password, because the first
573509
// sa password has been in the docker environment (as SA_PASSWORD)
574-
c.query(fmt.Sprintf("ALTER LOGIN [sa] WITH PASSWORD = N'%s';",
510+
c.sql.Query(fmt.Sprintf("ALTER LOGIN [sa] WITH PASSWORD = N'%s';",
575511
c.generatePassword()))
576-
c.query("ALTER LOGIN [sa] DISABLE")
512+
c.sql.Query("ALTER LOGIN [sa] DISABLE")
577513

578514
if c.defaultDatabase != "" {
579-
c.query(fmt.Sprintf("ALTER AUTHORIZATION ON DATABASE::[%s] TO %s",
515+
c.sql.Query(fmt.Sprintf("ALTER AUTHORIZATION ON DATABASE::[%s] TO %s",
580516
defaultDatabase, userName))
581517
}
582518
}
583519

584-
func extractUrl(usingArg string) string {
585-
urlEndIdx := strings.LastIndex(usingArg, ".bak")
586-
if urlEndIdx == -1 {
587-
urlEndIdx = strings.LastIndex(usingArg, ".mdf")
588-
}
589-
if urlEndIdx != -1 {
590-
return usingArg[0:(urlEndIdx + 4)]
591-
}
592-
593-
if urlEndIdx == -1 {
594-
urlEndIdx = strings.LastIndex(usingArg, ".7z")
595-
if urlEndIdx != -1 {
596-
return usingArg[0:(urlEndIdx + 3)]
597-
}
598-
}
599-
600-
if urlEndIdx == -1 {
601-
urlEndIdx = strings.LastIndex(usingArg, ".bacpac")
602-
if urlEndIdx != -1 {
603-
return usingArg[0:(urlEndIdx + 7)]
604-
}
605-
}
606-
607-
return usingArg
608-
}
609-
610-
func (c *MssqlBase) downloadAndRestoreDb(
611-
controller *container.Controller,
612-
containerId string,
613-
userName string,
614-
password string,
615-
) {
616-
mssqlcontainer.DownloadAndRestoreDb(
617-
controller,
618-
containerId,
619-
c.usingDatabaseUrl,
620-
userName,
621-
password,
622-
c.query,
623-
c.Cmd.Output(),
624-
)
625-
}
626-
627520
func (c *MssqlBase) downloadImage(
628521
imageName string,
629522
output *output.Output,
@@ -647,15 +540,6 @@ func (c *MssqlBase) downloadImage(
647540
}
648541
}
649542

650-
// Verify the file exists at the URL
651-
func urlExists(url string, output *output.Output) {
652-
if !http.UrlExists(url) {
653-
output.FatalfWithHints(
654-
[]string{"File does not exist at URL"},
655-
"Unable to download file")
656-
}
657-
}
658-
659543
func (c *MssqlBase) generatePassword() (password string) {
660544
password = secret.Generate(
661545
c.passwordLength,

cmd/modern/root/install/mssql-base_test.go

Lines changed: 0 additions & 24 deletions
This file was deleted.

cmd/modern/root/system.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
package root
5+
6+
import (
7+
"github.com/microsoft/go-sqlcmd/cmd/modern/root/system"
8+
"github.com/microsoft/go-sqlcmd/internal/cmdparser"
9+
)
10+
11+
// Config defines the `sqlcmd system` sub-commands
12+
type System struct {
13+
cmdparser.Cmd
14+
}
15+
16+
func (c *System) DefineCommand(...cmdparser.CommandOptions) {
17+
options := cmdparser.CommandOptions{
18+
Use: "system",
19+
Short: `Modify system wide options like the protocol handler or container runtime cache"`,
20+
SubCommands: c.SubCommands(),
21+
Examples: []cmdparser.ExampleOptions{
22+
{
23+
Description: "Register the sqlcmd:// protocol handler",
24+
Steps: []string{
25+
"sqlcmd system protocol add-handler"},
26+
},
27+
},
28+
}
29+
30+
c.Cmd.DefineCommand(options)
31+
}
32+
33+
// SubCommands sets up all the sub-commands for `sqlcmd config`
34+
func (c *System) SubCommands() []cmdparser.Command {
35+
dependencies := c.Dependencies()
36+
37+
return []cmdparser.Command{
38+
cmdparser.New[*system.Protocol](dependencies),
39+
}
40+
}

cmd/modern/root/system/protocol.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
package system
5+
6+
import (
7+
"fmt"
8+
"github.com/microsoft/go-sqlcmd/cmd/modern/root/system/protocol"
9+
"github.com/microsoft/go-sqlcmd/internal/cmdparser"
10+
"github.com/microsoft/go-sqlcmd/internal/pal"
11+
)
12+
13+
// Protocol defines the `sqlcmd system protocol` sub-commands
14+
type Protocol struct {
15+
cmdparser.Cmd
16+
}
17+
18+
func (c *Protocol) DefineCommand(...cmdparser.CommandOptions) {
19+
options := cmdparser.CommandOptions{
20+
Use: "protocol",
21+
Short: `Register/Unregsiter the sqlcmd:// protocol handler`,
22+
SubCommands: c.SubCommands(),
23+
Examples: []cmdparser.ExampleOptions{
24+
{
25+
Description: "Add context for existing endpoint and user (use SQLCMD_PASSWORD or SQLCMDPASSWORD)",
26+
Steps: []string{
27+
fmt.Sprintf("%s SQLCMD_PASSWORD=<placeholderpassword>", pal.CreateEnvVarKeyword()),
28+
"sqlcmd config add-user --name sa1434 --username sa",
29+
fmt.Sprintf("%s SQLCMD_PASSWORD=", pal.CreateEnvVarKeyword()),
30+
"sqlcmd config add-endpoint --name ep1434 --address localhost --port 1434",
31+
"sqlcmd config add-context --name mssql1434 --user sa1434 --endpoint ep1434"},
32+
},
33+
},
34+
}
35+
36+
c.Cmd.DefineCommand(options)
37+
}
38+
39+
// SubCommands sets up all the sub-commands for `sqlcmd config`
40+
func (c *Protocol) SubCommands() []cmdparser.Command {
41+
dependencies := c.Dependencies()
42+
43+
return []cmdparser.Command{
44+
cmdparser.New[*protocol.AddHandler](dependencies),
45+
cmdparser.New[*protocol.DeleteHandler](dependencies),
46+
}
47+
}

0 commit comments

Comments
 (0)