Skip to content

Commit 3bae8a2

Browse files
authored
Fix Frontend Observability App import (#2155)
* feat(fe-o11y): Add Frontend Observability App Import This commit adds support to import existing apps into Terraform Closes: #2115 * fix(feo11y): Fix Frontend Observbility App Update Inconsistency This commit fixes an issue where the collector endpoint would not be populated correctly when updating an App. This was happening because Frontend Observbility API will not return the collector URL on app update.
1 parent d245cd5 commit 3bae8a2

File tree

3 files changed

+104
-0
lines changed

3 files changed

+104
-0
lines changed

docs/index.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,29 @@ provider "grafana" {
262262
}
263263
```
264264

265+
#### Import existing Frontend Observability apps into Terraform
266+
267+
To manage an existing Frontend Observability app with Terraform, you can import it into your Terraform state.
268+
269+
##### Before you begin
270+
271+
You will need the following:
272+
273+
- **Stack slug** – This is the first part of your Grafana Cloud URL. For example, in `https://mystack.grafana.net`, the stack slug is `mystack`.
274+
275+
- **App ID** – Navigate to the app in your Grafana Cloud instance and copy the ID from the URL. It will look like this: `https://<stack-slug>.grafana.net/a/grafana-kowalski-app/apps/<app-id>`
276+
277+
278+
##### Import command
279+
280+
Run the following command to import the app into your Terraform state:
281+
282+
```bash
283+
terraform import '<stack-slug>:<app-id>' my-app
284+
```
285+
286+
Replace <stack-slug> and <app-id> with the appropriate values for your environment.
287+
265288
<!-- schema generated by tfplugindocs -->
266289
## Schema
267290

internal/resources/frontendo11y/resource_frontend_o11y_app.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"errors"
66
"fmt"
77
"net/http"
8+
"strconv"
9+
"strings"
810

911
"github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator"
1012
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
@@ -25,6 +27,9 @@ import (
2527
var (
2628
resourceFrontendO11yAppName = "grafana_frontend_o11y_app"
2729
resourceFrontendO11yAppTerraformID = common.NewResourceID(common.StringIDField("stack_id"), common.StringIDField("name"))
30+
31+
// Check interface
32+
_ resource.ResourceWithImportState = (*resourceFrontendO11yApp)(nil)
2833
)
2934

3035
type resourceFrontendO11yApp struct {
@@ -135,6 +140,22 @@ func (r *resourceFrontendO11yApp) getStackCluster(ctx context.Context, stackID s
135140
return stack.ClusterSlug, nil
136141
}
137142

143+
func (r *resourceFrontendO11yApp) getStack(ctx context.Context, stackID string) (*gcom.FormattedApiInstance, error) {
144+
stack, res, err := r.gcomClient.InstancesAPI.GetInstance(ctx, stackID).Execute()
145+
if err != nil {
146+
return nil, err
147+
}
148+
149+
if res.StatusCode >= 500 {
150+
return nil, errors.New("server error")
151+
}
152+
153+
if res.StatusCode == http.StatusNotFound {
154+
return nil, fmt.Errorf("stack %q not found", stackID)
155+
}
156+
return stack, nil
157+
}
158+
138159
func (r *resourceFrontendO11yApp) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
139160
var dataTF FrontendO11yAppTFModel
140161
diags := req.Plan.Get(ctx, &dataTF)
@@ -163,6 +184,42 @@ func (r *resourceFrontendO11yApp) Create(ctx context.Context, req resource.Creat
163184
resp.State.Set(ctx, appTFState)
164185
}
165186

187+
func (r *resourceFrontendO11yApp) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
188+
reqParts := strings.Split(req.ID, ":")
189+
if len(reqParts) != 2 {
190+
resp.Diagnostics.AddError("incorrect ID format", "Resource ID should be in the format of 'stackID:appID'")
191+
return
192+
}
193+
stackSlug := reqParts[0]
194+
appID := reqParts[1]
195+
i64AppID, err := strconv.ParseInt(appID, 10, 64)
196+
if err != nil {
197+
resp.Diagnostics.AddError("invalid app ID", err.Error())
198+
return
199+
}
200+
201+
stack, err := r.getStack(ctx, stackSlug)
202+
if err != nil {
203+
resp.Diagnostics.AddError("failed to get Grafana Cloud Stack information", err.Error())
204+
return
205+
}
206+
appClientModel, err := r.client.GetApp(
207+
ctx,
208+
apiURLForCluster(stack.ClusterSlug, r.client.Host()),
209+
int64(stack.Id),
210+
i64AppID,
211+
)
212+
213+
if err != nil {
214+
resp.Diagnostics.AddError("failed to get frontend o11y app", err.Error())
215+
return
216+
}
217+
218+
clientTFData, diags := convertClientModelToTFModel(int64(stack.Id), appClientModel)
219+
resp.Diagnostics.Append(diags...)
220+
resp.State.Set(ctx, clientTFData)
221+
}
222+
166223
func (r *resourceFrontendO11yApp) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
167224
var dataTF FrontendO11yAppTFModel
168225
diags := req.State.Get(ctx, &dataTF)
@@ -221,6 +278,7 @@ func (r *resourceFrontendO11yApp) Update(ctx context.Context, req resource.Updat
221278
}
222279

223280
appTFState, diags := convertClientModelToTFModel(dataTF.StackID.ValueInt64(), appClientModel)
281+
appTFState.CollectorEndpoint = dataTF.CollectorEndpoint
224282
resp.Diagnostics.Append(diags...)
225283
resp.State.Set(ctx, appTFState)
226284
}

templates/index.md.tmpl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,29 @@ provider "grafana" {
5555
}
5656
```
5757

58+
#### Import existing Frontend Observability apps into Terraform
59+
60+
To manage an existing Frontend Observability app with Terraform, you can import it into your Terraform state.
61+
62+
##### Before you begin
63+
64+
You will need the following:
65+
66+
- **Stack slug** – This is the first part of your Grafana Cloud URL. For example, in `https://mystack.grafana.net`, the stack slug is `mystack`.
67+
68+
- **App ID** – Navigate to the app in your Grafana Cloud instance and copy the ID from the URL. It will look like this: `https://<stack-slug>.grafana.net/a/grafana-kowalski-app/apps/<app-id>`
69+
70+
71+
##### Import command
72+
73+
Run the following command to import the app into your Terraform state:
74+
75+
```bash
76+
terraform import '<stack-slug>:<app-id>' my-app
77+
```
78+
79+
Replace <stack-slug> and <app-id> with the appropriate values for your environment.
80+
5881
{{ .SchemaMarkdown | trimspace }}
5982

6083
### Managing Cloud Provider

0 commit comments

Comments
 (0)