Repository: cloudflare/cloudflare-go
Pull request #3529 (2024-10-28 13:42:15)

FLPROD-796: Extend snippet interface with DELETE and GET a single sni…
Adding missing method to Get and Delete a single snippet



Patch:
diff --git a/.changelog/3510.txt b/.changelog/3510.txt
deleted file mode 100644
index 1dcd44cc7..000000000
--- a/.changelog/3510.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-```release-note:enhancement
-access_application: add support for controlling schema strictness in Access SCIM application provisioning mappings
-```
\ No newline at end of file
diff --git a/.changelog/3529.txt b/.changelog/3529.txt
new file mode 100644
index 000000000..32da23d64
--- /dev/null
+++ b/.changelog/3529.txt
@@ -0,0 +1,3 @@
+```release-note:enhancement
+snippets: add missing delete and get a single snippet methods
+```
diff --git a/access_application.go b/access_application.go
index 337be0035..2944cf114 100644
--- a/access_application.go
+++ b/access_application.go
@@ -163,7 +163,6 @@ type AccessApplicationScimMapping struct {
 	Filter           string                                  `json:"filter,omitempty"`
 	TransformJsonata string                                  `json:"transform_jsonata,omitempty"`
 	Operations       *AccessApplicationScimMappingOperations `json:"operations,omitempty"`
-	Strictness       string                                  `json:"strictness,omitempty"`
 }
 
 type AccessApplicationScimMappingOperations struct {
diff --git a/snippets.go b/snippets.go
index 870b8f73a..d21ea6885 100644
--- a/snippets.go
+++ b/snippets.go
@@ -3,6 +3,7 @@ package cloudflare
 import (
 	"bytes"
 	"context"
+	"errors"
 	"fmt"
 	"mime/multipart"
 	"net/http"
@@ -16,6 +17,11 @@ type SnippetsResponse struct {
 	Result []Snippet `json:"result"`
 }
 
+type SnippetResponse struct {
+	Response
+	Result *Snippet `json:"result"`
+}
+
 type Snippet struct {
 	CreatedOn   *time.Time `json:"created_on"`
 	ModifiedOn  *time.Time `json:"modified_on"`
@@ -33,6 +39,48 @@ type SnippetRequest struct {
 	Files       []SnippetFile `json:"files"`
 }
 
+func (api *API) DeleteZoneSnippet(ctx context.Context, rc *ResourceContainer, snippetName string) error {
+	if rc.Identifier == "" {
+		return ErrMissingZoneID
+	}
+
+	uri := buildURI(fmt.Sprintf("/zones/%s/snippets/%s", rc.Identifier, snippetName), nil)
+	res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
+	if err != nil {
+		return err
+	}
+
+	result := SnippetResponse{}
+	if err := json.Unmarshal(res, &result); err != nil {
+		return fmt.Errorf("%s: %w", errUnmarshalError, err)
+	}
+
+	if !result.Success {
+		return errors.New(result.Messages[0].Message)
+	}
+
+	return nil
+}
+
+func (api *API) GetZoneSnippet(ctx context.Context, rc *ResourceContainer, snippetName string) (*Snippet, error) {
+	if rc.Identifier == "" {
+		return nil, ErrMissingZoneID
+	}
+
+	uri := buildURI(fmt.Sprintf("/zones/%s/snippets/%s", rc.Identifier, snippetName), nil)
+	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	result := SnippetResponse{}
+	if err := json.Unmarshal(res, &result); err != nil {
+		return nil, fmt.Errorf("%s: %w", errUnmarshalError, err)
+	}
+
+	return result.Result, nil
+}
+
 func (api *API) ListZoneSnippets(ctx context.Context, rc *ResourceContainer) ([]Snippet, error) {
 	if rc.Identifier == "" {
 		return nil, ErrMissingZoneID


Test patch:
diff --git a/access_application_test.go b/access_application_test.go
index 589bb8fc9..50f2c7e66 100644
--- a/access_application_test.go
+++ b/access_application_test.go
@@ -1418,8 +1418,7 @@ func TestCreateAccessApplicationWithSCIMProvisioning(t *testing.T) {
 								"create": true,
 								"update": true,
 								"delete": true
-							},
-							"strictness": "passthrough"
+							}
 						}
 					]
 				}
@@ -1472,7 +1471,6 @@ func TestCreateAccessApplicationWithSCIMProvisioning(t *testing.T) {
 						Update: BoolPtr(true),
 						Delete: BoolPtr(true),
 					},
-					Strictness: "passthrough",
 				},
 			},
 		},
@@ -1504,7 +1502,6 @@ func TestCreateAccessApplicationWithSCIMProvisioning(t *testing.T) {
 						Update: BoolPtr(true),
 						Delete: BoolPtr(true),
 					},
-					Strictness: "strict",
 				},
 			},
 		},
@@ -1540,7 +1537,6 @@ func TestCreateAccessApplicationWithSCIMProvisioning(t *testing.T) {
 						Update: BoolPtr(true),
 						Delete: BoolPtr(true),
 					},
-					Strictness: "strict",
 				},
 			},
 		},
diff --git a/snippets_test.go b/snippets_test.go
index 627b3cb55..805a9f21f 100644
--- a/snippets_test.go
+++ b/snippets_test.go
@@ -56,6 +56,58 @@ func TestSnippets(t *testing.T) {
 	}
 }
 
+func TestGetSnippet(t *testing.T) {
+	setup()
+	defer teardown()
+
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
+		w.Header().Set("content-type", "application/json")
+		fmt.Fprint(w, `{
+      "result": {
+			"snippet_name": "some_id_1",
+			"created_on":"0001-01-01T00:00:00Z",
+			"modified_on":"0001-01-01T00:00:00Z"
+		},
+      "success": true,
+      "errors": [],
+      "messages": []
+    }`)
+	}
+	mux.HandleFunc("/zones/"+testZoneID+"/snippets/some_id_1", handler)
+
+	want := Snippet{
+		SnippetName: "some_id_1",
+		CreatedOn:   &time.Time{},
+		ModifiedOn:  &time.Time{},
+	}
+
+	zoneActual, err := client.GetZoneSnippet(context.Background(), ZoneIdentifier(testZoneID), "some_id_1")
+	if assert.NoError(t, err) {
+		assert.Equal(t, want, *zoneActual)
+	}
+}
+
+func TestDeleteSnippet(t *testing.T) {
+	setup()
+	defer teardown()
+
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method)
+		w.Header().Set("content-type", "application/json")
+		fmt.Fprint(w, `{
+			"result": null,
+			"success": true,
+			"errors": [],
+			"messages": []
+		}`)
+	}
+	mux.HandleFunc("/zones/"+testZoneID+"/snippets/some_id_1", handler)
+
+	err := client.DeleteZoneSnippet(context.Background(), ZoneIdentifier(testZoneID), "some_id_1")
+	assert.NoError(t, err)
+}
+
 func TestUpdateSnippets(t *testing.T) {
 	setup()
 	defer teardown()