77 "io"
88 "io/fs"
99 "net/http"
10+ "net/url"
1011 "os"
1112 "path/filepath"
1213 "regexp"
@@ -15,12 +16,13 @@ import (
1516 "github.com/spf13/cobra"
1617 "github.com/spf13/viper"
1718
19+ "github.com/launchdarkly/ldcli/cmd/cliflags"
1820 resourcescmd "github.com/launchdarkly/ldcli/cmd/resources"
21+ "github.com/launchdarkly/ldcli/internal/output"
1922 "github.com/launchdarkly/ldcli/internal/resources"
2023)
2124
2225const (
23- apiKeyFlag = "api-key"
2426 appVersionFlag = "app-version"
2527 pathFlag = "path"
2628 basePathFlag = "base-path"
@@ -30,8 +32,8 @@ const (
3032 defaultBackendUrl = "https://pri.observability.app.launchdarkly.com"
3133
3234 verifyApiKeyQuery = `
33- query ApiKeyToOrgID($api_key : String!) {
34- api_key_to_org_id(api_key: $api_key)
35+ query LDCredentialToAPIKey($ld_account_id: String!, $ld_project_id : String!) {
36+ ld_credential_to_api_key(ld_account_id: String!, ld_project_id: String!): String!
3537 }
3638 `
3739
@@ -44,8 +46,11 @@ const (
4446
4547type ApiKeyResponse struct {
4648 Data struct {
47- ApiKeyToOrgID string `json:"api_key_to_org_id "`
49+ APIKey string `json:"ld_credential_to_api_key "`
4850 } `json:"data"`
51+ Errors []struct {
52+ Message string `json:"message"`
53+ } `json:"errors"`
4954}
5055
5156type SourceMapUrlsResponse struct {
@@ -75,21 +80,67 @@ func NewUploadCmd(client resources.Client) *cobra.Command {
7580
7681func runE (client resources.Client ) func (cmd * cobra.Command , args []string ) error {
7782 return func (cmd * cobra.Command , args []string ) error {
78- apiKey := viper .GetString (apiKeyFlag )
83+ apiKey := viper .GetString (cliflags .AccessTokenFlag )
84+ u , _ := url .JoinPath (
85+ viper .GetString (cliflags .BaseURIFlag ),
86+ "api/v2/caller-identity" ,
87+ )
88+ res , err := client .MakeRequest (
89+ viper .GetString (cliflags .AccessTokenFlag ),
90+ "GET" ,
91+ u ,
92+ "application/json" ,
93+ nil ,
94+ nil ,
95+ false ,
96+ )
97+ if err != nil {
98+ return output .NewCmdOutputError (err , viper .GetString (cliflags .OutputFlag ))
99+ }
100+
101+ var result struct { AccountID string }
102+ if err = json .Unmarshal (res , & result ); err != nil {
103+ return output .NewCmdOutputError (err , viper .GetString (cliflags .OutputFlag ))
104+ }
105+
106+ projectKey := viper .GetString (cliflags .ProjectFlag )
107+ u , _ = url .JoinPath (
108+ viper .GetString (cliflags .BaseURIFlag ),
109+ "api/v2/projects" ,
110+ projectKey ,
111+ )
112+ res , err = client .MakeRequest (
113+ viper .GetString (cliflags .AccessTokenFlag ),
114+ "GET" ,
115+ u ,
116+ "application/json" ,
117+ nil ,
118+ nil ,
119+ false ,
120+ )
121+ if err != nil {
122+ return output .NewCmdOutputError (err , viper .GetString (cliflags .OutputFlag ))
123+ }
124+
125+ var projectResult struct {
126+ Items []struct {
127+ ID string `json:"_id"`
128+ }
129+ }
130+ if err = json .Unmarshal (res , & projectResult ); err != nil {
131+ return output .NewCmdOutputError (err , viper .GetString (cliflags .OutputFlag ))
132+ }
133+
79134 appVersion := viper .GetString (appVersionFlag )
80135 path := viper .GetString (pathFlag )
81136 basePath := viper .GetString (basePathFlag )
82137 backendUrl := viper .GetString (backendUrlFlag )
83138
84- if apiKey == "" {
85- return fmt .Errorf ("api key cannot be empty" )
86- }
87-
88139 if backendUrl == "" {
89140 backendUrl = defaultBackendUrl
90141 }
91142
92- organizationID , err := verifyApiKey (apiKey , backendUrl )
143+ organizationID , err := verifyApiKey (result . AccountID , projectResult . Items [ 0 ]. ID , backendUrl )
93144 if err != nil {
94145 return fmt .Errorf ("failed to verify API key: %v" , err )
95146 }
@@ -126,9 +177,10 @@ func runE(client resources.Client) func(cmd *cobra.Command, args []string) error
126177 }
127178}
128179
129- func verifyApiKey (apiKey , backendUrl string ) (string , error ) {
180+ func verifyApiKey (accountID , projectID , backendUrl string ) (string , error ) {
130181 variables := map [string ]string {
131- "api_key" : apiKey ,
182+ "ld_account_id" : accountID ,
183+ "ld_project_id" : projectID ,
132184 }
133185
134186 reqBody , err := json .Marshal (map [string ]interface {}{
@@ -145,7 +197,6 @@ func verifyApiKey(apiKey, backendUrl string) (string, error) {
145197 }
146198
147199 req .Header .Set ("Content-Type" , "application/json" )
148- req .Header .Set ("ApiKey" , apiKey )
149200
150201 client := & http.Client {}
151202 resp , err := client .Do (req )
@@ -164,11 +215,15 @@ func verifyApiKey(apiKey, backendUrl string) (string, error) {
164215 return "" , err
165216 }
166217
167- if apiKeyResp .Data .ApiKeyToOrgID == "" || apiKeyResp .Data .ApiKeyToOrgID == "0" {
218+ if len (apiKeyResp .Errors ) > 0 {
219+ return "" , fmt .Errorf ("failed to verify API key: %s" , apiKeyResp .Errors [0 ].Message )
220+ }
221+
222+ if apiKeyResp .Data .APIKey == "" {
168223 return "" , fmt .Errorf ("invalid API key" )
169224 }
170225
171- return apiKeyResp .Data .ApiKeyToOrgID , nil
226+ return apiKeyResp .Data .APIKey , nil
172227}
173228
174229func getAllSourceMapFiles (path string ) ([]SourceMapFile , error ) {
@@ -315,10 +370,10 @@ func uploadFile(filePath, uploadUrl, name string) error {
315370}
316371
317372func initFlags (cmd * cobra.Command ) {
318- cmd .Flags ().String (apiKeyFlag , "" , "The LaunchDarkly Observability API key" )
319- _ = cmd .MarkFlagRequired (apiKeyFlag )
320- _ = cmd .Flags ().SetAnnotation (apiKeyFlag , "required" , []string {"true" })
321- _ = viper .BindPFlag (apiKeyFlag , cmd .Flags ().Lookup (apiKeyFlag ))
373+ cmd .Flags ().String (cliflags . ProjectFlag , "" , "The project key" )
374+ _ = cmd .MarkFlagRequired (cliflags . ProjectFlag )
375+ _ = cmd .Flags ().SetAnnotation (cliflags . ProjectFlag , "required" , []string {"true" })
376+ _ = viper .BindPFlag (cliflags . ProjectFlag , cmd .Flags ().Lookup (cliflags . ProjectFlag ))
322377
323378 cmd .Flags ().String (appVersionFlag , "" , "The current version of your deploy" )
324379 _ = viper .BindPFlag (appVersionFlag , cmd .Flags ().Lookup (appVersionFlag ))
0 commit comments