-
Notifications
You must be signed in to change notification settings - Fork 37
Oas bot 32379860790/ufw #10428
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
alextiugan15
wants to merge
9
commits into
stackitcloud:oas-bot-32379860790/ufw
Choose a base branch
from
alextiugan15:oas-bot-32379860790/ufw
base: oas-bot-32379860790/ufw
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Oas bot 32379860790/ufw #10428
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
9561658
Generate ufw
stackit-pipeline 018dfe8
- added ufw to go.work file
alexTiugan 194052f
- fixed linter
alexTiugan d1ba973
Generate ufw
stackit-pipeline 5a6197d
Merge branch 'oas-bot-32239425179/ufw' into oas-bot-32343214600/ufw
alexTiugan f0bc912
- added listing as first request call to trigger the sync
alexTiugan 57c9c14
- added go.sum
alexTiugan 4409b04
Merge branch 'oas-bot-32343214600/ufw' into oas-bot-32379860790/ufw
alexTiugan 2b83660
- updated status to be ufw.RuleResponseStatus type
alexTiugan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| module github.com/stackitcloud/stackit-sdk-go/examples/ufw | ||
|
|
||
| go 1.25.9 | ||
|
|
||
| replace github.com/stackitcloud/stackit-sdk-go/services/ufw => ../../services/ufw | ||
|
|
||
| require ( | ||
| github.com/stackitcloud/stackit-sdk-go/core v0.26.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/ufw v0.0.0-00010101000000-000000000000 | ||
| ) | ||
|
|
||
| require ( | ||
| github.com/golang-jwt/jwt/v5 v5.3.1 // indirect | ||
| github.com/google/uuid v1.6.0 // indirect | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= | ||
| github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= | ||
| github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= | ||
| github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= | ||
| github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= | ||
| github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||
| github.com/stackitcloud/stackit-sdk-go/core v0.26.0 h1:jQEb9gkehfp6VCP6TcYk7BI10cz4l0KM2L6hqYBH2QA= | ||
| github.com/stackitcloud/stackit-sdk-go/core v0.26.0/go.mod h1:WU1hhxnjXw2EV7CYa1nlEvNpMiRY6CvmIOaHuL3pOaA= |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,240 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "os" | ||
| "reflect" | ||
| "strings" | ||
|
|
||
| "github.com/stackitcloud/stackit-sdk-go/core/config" | ||
| ufw "github.com/stackitcloud/stackit-sdk-go/services/ufw/v1api" | ||
| "github.com/stackitcloud/stackit-sdk-go/services/ufw/v1api/wait" | ||
| ) | ||
|
|
||
| func main() { | ||
| region := "eu01" // Region where the resources will be created | ||
| projectId := "PROJECT_ID" // UUID of your STACKIT project | ||
| instanceId := "INSTANCE_ID" // UUID of the instance to which the firewall rule will be attached | ||
| productType := "PRODUCT_TYPE" // Type of the instance to which the firewall rule will be attached (e.g. "redis", but you can get them from provider-options route) | ||
| ufwRuleType := "ACL" // Type of the rule that you want to create (ACL, SecurityRule, PublicIp, but you can get them from provider-options route | ||
|
|
||
| ctx := context.Background() | ||
|
|
||
| token := "" | ||
| ufwClient, err := ufw.NewAPIClient(config.WithToken(token)) | ||
| if err != nil { | ||
| fmt.Fprintf(os.Stderr, "[UFW] Creating API client: %v\n", err) | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| // List all firewall rules | ||
| listUFWRules(ctx, ufwClient, projectId, region) | ||
|
|
||
| // Create a new firewall rule | ||
| description := "Created from SDK" | ||
| rulePayloadToCreate := ufw.CreateRulePayload{ | ||
| InstanceId: instanceId, | ||
| Product: productType, | ||
| SourceIP: "11.11.11.11/32", | ||
| Type: ufwRuleType, | ||
| Description: &description, | ||
| } | ||
|
|
||
| createdRuleResponse, err := createFirewallRule(ctx, ufwClient, projectId, region, &rulePayloadToCreate) | ||
|
|
||
| if err != nil { | ||
| fmt.Fprintf(os.Stderr, "[UFW] Error when creating firewall rule: %v\n", err) | ||
| return | ||
| } | ||
|
|
||
| fmt.Printf("Created firewall rule response: %+v\n", createdRuleResponse) | ||
|
|
||
| // Get the firewall rule | ||
| testGetRule, err := getFirewallRule(ctx, ufwClient, projectId, region, *createdRuleResponse.RefId) | ||
| if err != nil { | ||
| fmt.Fprintf(os.Stderr, "[UFW] Error when getting firewall rule: %v\n", err) | ||
| return | ||
| } | ||
|
|
||
| fmt.Printf("Firewall rule details: %+v\n", testGetRule) | ||
|
|
||
| if err := verifyPayloadMatch(testGetRule, rulePayloadToCreate); err != nil { | ||
| fmt.Fprintf(os.Stderr, "[UFW] Verification failed after creation:\n%v\n", err) | ||
| return | ||
| } | ||
| fmt.Println("Created rule fields verified successfully.") | ||
|
|
||
| // Update the firewall rule | ||
| rulePayloadToUpdate := ufw.UpdateRulePayload{ | ||
| SourceIP: "22.22.22.22/32", | ||
| } | ||
|
|
||
| updatedRuleResponse, err := updateFirewallRule(ctx, ufwClient, projectId, region, *createdRuleResponse.RefId, rulePayloadToUpdate) | ||
|
|
||
| if err != nil { | ||
| fmt.Fprintf(os.Stderr, "[UFW] Error when updating firewall rule: %v\n", err) | ||
| return | ||
| } | ||
|
|
||
| fmt.Printf("Updated firewall rule details: %+v\n", updatedRuleResponse) | ||
|
|
||
| testGetRule, err = getFirewallRule(ctx, ufwClient, projectId, region, *updatedRuleResponse.RefId) | ||
| if err != nil { | ||
| fmt.Fprintf(os.Stderr, "[UFW] Error when getting updated firewall rule: %v\n", err) | ||
| return | ||
| } | ||
|
|
||
| if err := verifyPayloadMatch(testGetRule, rulePayloadToUpdate); err != nil { | ||
| fmt.Fprintf(os.Stderr, "[UFW] Verification failed after update:\n%v\n", err) | ||
| return | ||
| } | ||
| fmt.Println("Updated rule fields verified successfully.") | ||
|
|
||
| // Delete the firewall rule | ||
| err = deleteFirewallRule(ctx, ufwClient, projectId, region, *updatedRuleResponse.RefId) | ||
| if err != nil { | ||
| fmt.Fprintf(os.Stderr, "[UFW] Error when deleting firewall rule: %v\n", err) | ||
| return | ||
| } | ||
|
|
||
| _, err = getFirewallRule(ctx, ufwClient, projectId, region, *updatedRuleResponse.RefId) | ||
| if !strings.Contains(err.Error(), "404") { | ||
| fmt.Fprintf(os.Stderr, "[UFW] Error while verifying deleted rule: %v\n", err) | ||
| return | ||
| } | ||
|
|
||
| fmt.Println("All firewall rules successfully tested and cleaned up.") | ||
| } | ||
|
|
||
| func listUFWRules(ctx context.Context, ufwClient *ufw.APIClient, projectId, region string) { | ||
| listRulesResponse, err := ufwClient.DefaultAPI.ListRules(ctx, projectId, region).Execute() | ||
| if err != nil { | ||
| fmt.Fprintf(os.Stderr, "[UFW] Error when listing firewall rules: %v\n", err) | ||
| return | ||
| } | ||
|
|
||
| fmt.Println("List of firewall rules:") | ||
| for i := range listRulesResponse.Rules { | ||
| fmt.Printf("%+v\n", listRulesResponse.Rules[i]) | ||
| } | ||
| } | ||
|
|
||
| func getFirewallRule(ctx context.Context, ufwClient *ufw.APIClient, projectId, region, ruleId string) (*ufw.RuleResponse, error) { | ||
| return ufwClient.DefaultAPI.GetRule(ctx, projectId, region, ruleId).Execute() | ||
| } | ||
|
|
||
| func createFirewallRule(ctx context.Context, ufwClient *ufw.APIClient, projectId, region string, payload *ufw.CreateRulePayload) (*ufw.SecurityRuleSuccessfullyCreatedResponse, error) { | ||
| createdFirewallRule, err := ufwClient.DefaultAPI.CreateRule(ctx, projectId, region).CreateRulePayload(*payload).Execute() | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| createdFirewallRuleId := createdFirewallRule.RefId | ||
| fmt.Printf("Created firewall rule with ID: %s\n", *createdFirewallRuleId) | ||
|
|
||
| _, err = wait.CreateRuleWaitHandler(ctx, ufwClient.DefaultAPI, projectId, region, *createdFirewallRuleId).WaitWithContext(ctx) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| return createdFirewallRule, nil | ||
| } | ||
|
|
||
| func updateFirewallRule(ctx context.Context, ufwClient *ufw.APIClient, projectId, region, ruleId string, payload ufw.UpdateRulePayload) (*ufw.SecurityRuleSuccessfullyCreatedResponse, error) { | ||
| updatedFirewallRule, err := ufwClient.DefaultAPI.UpdateRule(ctx, projectId, region, ruleId).UpdateRulePayload(payload).Execute() | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| fmt.Printf("Updated firewall rule with ID: %s\n", *updatedFirewallRule.RefId) | ||
|
|
||
| _, err = wait.UpdateRuleWaitHandler(ctx, ufwClient.DefaultAPI, projectId, region, *updatedFirewallRule.RefId).WaitWithContext(ctx) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| return updatedFirewallRule, nil | ||
| } | ||
|
|
||
| func deleteFirewallRule(ctx context.Context, ufwClient *ufw.APIClient, projectId, region, ruleId string) error { | ||
| deleteRuleResponse, err := ufwClient.DefaultAPI.DeleteRule(ctx, projectId, region, ruleId).Execute() | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| fmt.Printf("Deleted firewall rule with ID: %s\n", ruleId) | ||
| fmt.Printf("Deleted firewall rule response: %+v\n", deleteRuleResponse) | ||
|
|
||
| _, err = wait.DeleteRuleWaitHandler(ctx, ufwClient.DefaultAPI, projectId, region, ruleId).WaitWithContext(ctx) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func verifyPayloadMatch(actual, expected any) error { | ||
| var mismatches []string | ||
|
|
||
| actualVal := reflect.ValueOf(actual) | ||
| if actualVal.Kind() == reflect.Pointer { | ||
| actualVal = actualVal.Elem() | ||
| } | ||
|
|
||
| expectedVal := reflect.ValueOf(expected) | ||
| if expectedVal.Kind() == reflect.Pointer { | ||
| expectedVal = expectedVal.Elem() | ||
| } | ||
|
|
||
| expectedType := expectedVal.Type() | ||
|
|
||
| for i := 0; i < expectedVal.NumField(); i++ { | ||
| fieldName := expectedType.Field(i).Name | ||
|
|
||
| if fieldName == "AdditionalProperties" { | ||
| continue // AdditionalProperties field is not part of the API response struct | ||
| } | ||
|
|
||
| if fieldName == "Description" { | ||
| continue // Description field is overridden by the API, will be fixed in the future | ||
| } | ||
|
|
||
| expectedField := expectedVal.Field(i) | ||
|
|
||
| // Look for a matching field in the API response struct | ||
| actualField := actualVal.FieldByName(fieldName) | ||
| if !actualField.IsValid() { | ||
| continue // Field exists in payload but not in response struct, safe to skip | ||
| } | ||
|
|
||
| // Dereference pointers cleanly to get string representations | ||
| expStr := formatReflectValue(expectedField) | ||
| actStr := formatReflectValue(actualField) | ||
|
|
||
| // Skip uninitialized/nil fields in the expected payload | ||
| // (e.g. fields omitted from an UpdateRulePayload) | ||
| if expStr == "" || expStr == "<nil>" { | ||
| continue | ||
| } | ||
|
|
||
| if expStr != actStr { | ||
| mismatches = append(mismatches, fmt.Sprintf("%s: expected %q, got %q", fieldName, expStr, actStr)) | ||
| } | ||
| } | ||
|
|
||
| if len(mismatches) > 0 { | ||
| return fmt.Errorf("field mismatches found:\n- %s", strings.Join(mismatches, "\n- ")) | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func formatReflectValue(v reflect.Value) string { | ||
| if v.Kind() == reflect.Pointer { | ||
| if v.IsNil() { | ||
| return "<nil>" | ||
| } | ||
| v = v.Elem() | ||
| } | ||
| return fmt.Sprintf("%v", v.Interface()) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package wait | ||
|
|
||
| import ( | ||
| "context" | ||
| "errors" | ||
| "net/http" | ||
| "time" | ||
|
|
||
| "github.com/stackitcloud/stackit-sdk-go/core/wait" | ||
| ufw "github.com/stackitcloud/stackit-sdk-go/services/ufw/v1api" | ||
| ) | ||
|
|
||
| func CreateRuleWaitHandler(ctx context.Context, a ufw.DefaultAPI, projectId, region, ruleId string) *wait.AsyncActionHandler[ufw.RuleResponse] { | ||
| return ruleWaitHandler(ctx, a, projectId, region, ruleId, []ufw.RuleResponseStatus{ufw.RULERESPONSESTATUS_ACTIVE}, nil) | ||
| } | ||
|
|
||
| func UpdateRuleWaitHandler(ctx context.Context, a ufw.DefaultAPI, projectId, region, ruleId string) *wait.AsyncActionHandler[ufw.RuleResponse] { | ||
| return ruleWaitHandler(ctx, a, projectId, region, ruleId, []ufw.RuleResponseStatus{ufw.RULERESPONSESTATUS_ACTIVE}, nil) | ||
| } | ||
|
|
||
| func DeleteRuleWaitHandler(ctx context.Context, a ufw.DefaultAPI, projectId, region, ruleId string) *wait.AsyncActionHandler[ufw.RuleResponse] { | ||
| return ruleWaitHandler(ctx, a, projectId, region, ruleId, nil, []int{http.StatusNotFound}) | ||
| } | ||
|
|
||
| func ruleWaitHandler(ctx context.Context, a ufw.DefaultAPI, projectId, region, ruleId string, activeStates []ufw.RuleResponseStatus, deleteHttpErrorStatusCodes []int) *wait.AsyncActionHandler[ufw.RuleResponse] { | ||
| waitConfig := wait.WaiterHelper[ufw.RuleResponse, ufw.RuleResponseStatus]{ | ||
| FetchInstance: a.GetRule(ctx, projectId, region, ruleId).Execute, | ||
| GetState: func(ruleResp *ufw.RuleResponse) (ufw.RuleResponseStatus, error) { | ||
| if ruleResp == nil { | ||
| return "", errors.New("empty response") | ||
| } | ||
| return *ruleResp.Status, nil | ||
| }, | ||
| ActiveState: activeStates, | ||
| ErrorState: []ufw.RuleResponseStatus{ufw.RULERESPONSESTATUS_ERROR}, | ||
| DeleteHttpErrorStatusCodes: deleteHttpErrorStatusCodes, | ||
| } | ||
|
|
||
| handler := wait.New(waitConfig.Wait()) | ||
| handler.SetTimeout(5 * time.Minute) | ||
| return handler | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah sorry, my earlier comment wasn't probably clear enough. Idea was to adjust the spec:
Statussounded like a required attribute.Please make it either required or reintroduce the nil check.