-
Notifications
You must be signed in to change notification settings - Fork 84
Expand file tree
/
Copy pathssms.go
More file actions
98 lines (79 loc) · 3.1 KB
/
ssms.go
File metadata and controls
98 lines (79 loc) · 3.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//go:build windows
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
package open
import (
"fmt"
"strings"
"github.com/microsoft/go-sqlcmd/cmd/modern/sqlconfig"
"github.com/microsoft/go-sqlcmd/internal/cmdparser"
"github.com/microsoft/go-sqlcmd/internal/config"
"github.com/microsoft/go-sqlcmd/internal/container"
"github.com/microsoft/go-sqlcmd/internal/localizer"
"github.com/microsoft/go-sqlcmd/internal/tools"
)
// Ssms implements the `sqlcmd open ssms` command. It opens
// SQL Server Management Studio and connects to the current context using the
// credentials specified in the context.
func (c *Ssms) DefineCommand(...cmdparser.CommandOptions) {
options := cmdparser.CommandOptions{
Use: "ssms",
Short: localizer.Sprintf("Open SQL Server Management Studio and connect to current context"),
Examples: []cmdparser.ExampleOptions{{
Description: localizer.Sprintf("Open SSMS and connect using the current context"),
Steps: []string{"sqlcmd open ssms"}}},
Run: c.run,
}
c.Cmd.DefineCommand(options)
}
// Launch SSMS and connect to the current context
func (c *Ssms) run() {
endpoint, user := config.CurrentContext()
// Check if this is a local container connection
isLocalConnection := isLocalEndpoint(endpoint)
// If the context has a local container, ensure it is running, otherwise bail out
if asset := endpoint.AssetDetails; asset != nil && asset.ContainerDetails != nil {
c.ensureContainerIsRunning(asset.Id)
}
// Launch SSMS with connection parameters
c.launchSsms(endpoint.Address, endpoint.Port, user, isLocalConnection)
}
func (c *Ssms) ensureContainerIsRunning(containerID string) {
output := c.Output()
controller := container.NewController()
if !controller.ContainerRunning(containerID) {
output.FatalWithHintExamples([][]string{
{localizer.Sprintf("To start the container"), localizer.Sprintf("sqlcmd start")},
}, localizer.Sprintf("Container is not running"))
}
}
// launchSsms launches SQL Server Management Studio using the specified server and user credentials.
func (c *Ssms) launchSsms(host string, port int, user *sqlconfig.User, isLocalConnection bool) {
output := c.Output()
// Build server connection string
serverArg := fmt.Sprintf("%s,%d", host, port)
args := []string{
"-S", serverArg,
"-nosplash",
}
// Only add -C (trust server certificate) for local connections with self-signed certs
if isLocalConnection {
args = append(args, "-C")
}
// Use SQL authentication if configured (commonly used for SQL Server containers)
if user != nil && user.AuthenticationType == "basic" && user.BasicAuth != nil {
// Escape double quotes in username (SQL Server allows " in login names)
username := strings.ReplaceAll(user.BasicAuth.Username, `"`, `\"`)
args = append(args, "-U", username)
// Note: -P parameter was removed in SSMS 18+ for security reasons
// Copy password to clipboard so user can paste it in the login dialog
copyPasswordToClipboard(user, output)
}
tool := tools.NewTool("ssms")
if !tool.IsInstalled() {
output.Fatal(tool.HowToInstall())
}
c.displayPreLaunchInfo()
_, err := tool.Run(args)
c.CheckErr(err)
}