api-gateway: migrate YAML gen + provider core from deck-api (?endpoint=) to lk-api-gateway (REST paths)
- service_spec_gen: callAPI() auto-detects proxy vs REST mode by index.cfm presence
- core/client.go: buildURL() replaces all 4 ?endpoint= harcoded sites
- build-provider.sh: -ldflags -X main.version=${VERSION} for correct binary version
- 01_generate_yamls.sh (devops + root): Python auto-detect proxy vs REST
- 02_generate_resources_and_docs_v2.sh: pass -api-endpoint to doc generators
- 04_build_and_publish_docs.sh: normalize_api_endpoint without forced /index.cfm
- docs_template_gen + v2: -api-endpoint flag, hardcoded deck-api replaced
- provider.go (both): TODO(api-gateway) comments
- profiles/test/profile.env: NUBES_API_ENDPOINT -> lk-api-gateway-test
- HISTORY: 2026-07-02_api_gateway_migration.md
This commit is contained in:
@@ -29,6 +29,31 @@ type UniversalClient struct {
|
||||
LogLevel string
|
||||
}
|
||||
|
||||
// isProxyAPI returns true if ApiEndpoint uses legacy ?endpoint= proxy pattern (contains "index.cfm").
|
||||
func (c *UniversalClient) isProxyAPI() bool {
|
||||
return strings.Contains(c.ApiEndpoint, "index.cfm")
|
||||
}
|
||||
|
||||
// buildURL constructs a full URL from the base endpoint + path.
|
||||
// Legacy proxy: index.cfm?endpoint=/instances&page=1
|
||||
// New REST gateway: /api/v1/svc/instances?page=1
|
||||
func (c *UniversalClient) buildURL(path string) string {
|
||||
if c.isProxyAPI() {
|
||||
endpointPath := path
|
||||
extraQuery := ""
|
||||
if idx := strings.Index(path, "?"); idx >= 0 {
|
||||
endpointPath = path[:idx]
|
||||
extraQuery = path[idx+1:]
|
||||
}
|
||||
rawQuery := "endpoint=" + endpointPath
|
||||
if extraQuery != "" {
|
||||
rawQuery += "&" + extraQuery
|
||||
}
|
||||
return c.ApiEndpoint + "?" + rawQuery
|
||||
}
|
||||
return c.ApiEndpoint + path
|
||||
}
|
||||
|
||||
// ctxKeyLogLevel — ключ для переопределения LogLevel на уровне ресурса через context.WithValue.
|
||||
type ctxKeyLogLevelType struct{}
|
||||
|
||||
@@ -512,7 +537,7 @@ func (c *UniversalClient) FindInstanceByDisplayName(ctx context.Context, service
|
||||
if len(found) == 0 {
|
||||
page := 1
|
||||
for {
|
||||
reqURL := fmt.Sprintf("%s?endpoint=/instances&page=%d&size=100", c.ApiEndpoint, page)
|
||||
reqURL := c.buildURL(fmt.Sprintf("/instances?page=%d&size=100", page))
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", reqURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -587,7 +612,7 @@ func (c *UniversalClient) FindInstanceByDisplayName(ctx context.Context, service
|
||||
}
|
||||
|
||||
func (c *UniversalClient) GetInstanceState(ctx context.Context, instanceUid string) (*InstanceStateResponse, error) {
|
||||
url := fmt.Sprintf("%s?endpoint=/instances/%s", c.ApiEndpoint, instanceUid)
|
||||
url := c.buildURL(fmt.Sprintf("/instances/%s", instanceUid))
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -634,7 +659,7 @@ func isInstanceDeleted(state *InstanceStateResponse) bool {
|
||||
// GetInstanceStateRaw получает состояние инстанса БЕЗ валидации статуса.
|
||||
// Используется для проверки ref-параметров: нужно читать даже deleted/suspended инстансы.
|
||||
func (c *UniversalClient) GetInstanceStateRaw(ctx context.Context, instanceUid string) (*InstanceStateResponse, error) {
|
||||
reqURL := fmt.Sprintf("%s?endpoint=/instances/%s", c.ApiEndpoint, instanceUid)
|
||||
reqURL := c.buildURL(fmt.Sprintf("/instances/%s", instanceUid))
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", reqURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -835,24 +860,12 @@ func (c *UniversalClient) doRequest(ctx context.Context, method, path string, pa
|
||||
body = bytes.NewBuffer(b)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, method, c.ApiEndpoint, body)
|
||||
reqURL := c.buildURL(path)
|
||||
req, err := http.NewRequestWithContext(ctx, method, reqURL, body)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// ?endpoint= формат — без url.Values.Encode (сохраняет / как /)
|
||||
endpointPath := path
|
||||
extraQuery := ""
|
||||
if idx := strings.Index(path, "?"); idx >= 0 {
|
||||
endpointPath = path[:idx]
|
||||
extraQuery = path[idx+1:]
|
||||
}
|
||||
rawQuery := "endpoint=" + endpointPath
|
||||
if extraQuery != "" {
|
||||
rawQuery += "&" + extraQuery
|
||||
}
|
||||
req.URL.RawQuery = rawQuery
|
||||
|
||||
// Форсируем новое TCP-соединение: DDoS-Guard может блочить POST на keep-alive
|
||||
req.Close = true
|
||||
|
||||
|
||||
@@ -92,6 +92,8 @@ func (p *NubesProvider) Configure(ctx context.Context, req provider.ConfigureReq
|
||||
return
|
||||
}
|
||||
|
||||
// TODO(api-gateway): default is legacy proxy (index.cfm?endpoint=).
|
||||
// core.UniversalClient still uses ?endpoint= pattern — needs migration to REST paths.
|
||||
apiEndpoint := "https://deck-api.ngcloud.ru/api/v1/index.cfm"
|
||||
apiToken := ""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user