Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"log/slog"
"os"
"path/filepath"
"strconv"
"strings"

"gopkg.in/yaml.v3"
Expand Down Expand Up @@ -150,6 +151,12 @@ func expandTiers(value string) map[string]bool {
}

func applyEnvOverrides(cfg *Config) {
if p := os.Getenv("DEVCLOUD_PORT"); p != "" {
if v, err := strconv.Atoi(p); err == nil {
cfg.Server.Port = v
}
}

if envServices := os.Getenv("DEVCLOUD_SERVICES"); envServices != "" {
allowed := expandTiers(envServices)
if allowed == nil {
Expand Down
6 changes: 5 additions & 1 deletion internal/services/bedrock/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,11 @@ func (p *Provider) listTagsForResource(arn string) (*plugin.Response, error) {
if err != nil {
return shared.JSONError("InternalError", err.Error(), http.StatusInternalServerError), nil
}
return shared.JSONResponse(http.StatusOK, map[string]any{"tags": tags})
tagList := make([]map[string]string, 0, len(tags))
for k, v := range tags {
tagList = append(tagList, map[string]string{"key": k, "value": v})
}
return shared.JSONResponse(http.StatusOK, map[string]any{"tags": tagList})
}

func (p *Provider) untagResource(arn string, keys []string) (*plugin.Response, error) {
Expand Down
22 changes: 17 additions & 5 deletions internal/services/bedrock/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,22 @@ func TestTagging(t *testing.T) {
resp2 := call(t, p, "GET", "/tags/"+testARN, "")
assert.Equal(t, 200, resp2.StatusCode)
rb2 := parseBody(t, resp2)
tags := rb2["tags"].(map[string]any)
assert.Equal(t, "test", tags["env"])

// Untag
resp3 := call(t, p, "DELETE", "/tags/"+testARN+"?tagKeys=env", "")
tagList := rb2["tags"].([]any)
tagMap := map[string]string{}
for _, t := range tagList {
tm := t.(map[string]any)
tagMap[tm["key"].(string)] = tm["value"].(string)
}
assert.Equal(t, "test", tagMap["env"])
Comment thread
sourcery-ai[bot] marked this conversation as resolved.

// Untag all
resp3 := call(t, p, "DELETE", "/tags/"+testARN+"?tagKeys=env&tagKeys=tier", "")
assert.Equal(t, 204, resp3.StatusCode)

// List after removing all tags
resp4 := call(t, p, "GET", "/tags/"+testARN, "")
assert.Equal(t, 200, resp4.StatusCode)
rb4 := parseBody(t, resp4)
emptyTags := rb4["tags"].([]any)
assert.Empty(t, emptyTags)
}
18 changes: 12 additions & 6 deletions internal/services/cloudwatch/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,12 +594,18 @@ func (p *Provider) describeAnomalyDetectors(jm bool, req *http.Request) (*plugin
}
list := make([]map[string]any, 0, len(detectors))
for _, d := range detectors {
list = append(list, map[string]any{
"Namespace": d.Namespace,
"MetricName": d.MetricName,
"Stat": d.Stat,
"Configuration": d.Configuration,
})
entry := map[string]any{
"Namespace": d.Namespace,
"MetricName": d.MetricName,
"Stat": d.Stat,
}
if d.Configuration != "" {
entry["Configuration"] = d.Configuration
}
if d.Dimensions != "" {
entry["Dimensions"] = d.Dimensions
}
list = append(list, entry)
}
return cwResp(jm, http.StatusOK, "DescribeAnomalyDetectorsResponse", map[string]any{
"AnomalyDetectors": list,
Expand Down
3 changes: 3 additions & 0 deletions internal/services/eventbridge/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,9 @@ func (s *EBStore) MatchingRules(busName, accountID string, event map[string]any)
return nil, err
}
eventSource, _ := event["source"].(string)
if eventSource == "" {
eventSource, _ = event["Source"].(string)
}
var matched []Rule
for _, r := range rules {
if r.State != "ENABLED" {
Expand Down
142 changes: 63 additions & 79 deletions internal/services/route53/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1507,27 +1507,20 @@ func (p *Provider) activateKeySigningKey(req *http.Request) (*plugin.Response, e
}
return nil, err
}
type xmlKeySigningKey struct {
Name string `xml:"Name"`
HostedZoneId string `xml:"HostedZoneId"`
KeyId string `xml:"KeyId"`
State string `xml:"State"`
Algorithm string `xml:"Algorithm"`
KeySpec string `xml:"KeySpec"`
PublishTime string `xml:"PublishTime"`
type xmlChangeInfo struct {
Id string `xml:"Id"`
Status string `xml:"Status"`
SubmittedAt string `xml:"SubmittedAt"`
}
type response struct {
XMLName xml.Name `xml:"ActivateKeySigningKeyResponse"`
KeySigningKey xmlKeySigningKey `xml:"KeySigningKey"`
XMLName xml.Name `xml:"ActivateKeySigningKeyResponse"`
ChangeInfo xmlChangeInfo `xml:"ChangeInfo"`
}
return xmlResp(http.StatusOK, response{
KeySigningKey: xmlKeySigningKey{
Name: name,
HostedZoneId: zoneID,
KeyId: generateID(),
State: "Signing",
Algorithm: "ECDSA_P256_SHA256",
KeySpec: "ECDSA_P256",
ChangeInfo: xmlChangeInfo{
Id: generateID(),
Status: "PENDING",
SubmittedAt: time.Now().UTC().Format(time.RFC3339),
},
})
}
Expand All @@ -1543,10 +1536,22 @@ func (p *Provider) deactivateKeySigningKey(req *http.Request) (*plugin.Response,
}
return nil, err
}
type xmlChangeInfo struct {
Id string `xml:"Id"`
Status string `xml:"Status"`
SubmittedAt string `xml:"SubmittedAt"`
}
type response struct {
XMLName xml.Name `xml:"DeactivateKeySigningKeyResponse"`
XMLName xml.Name `xml:"DeactivateKeySigningKeyResponse"`
ChangeInfo xmlChangeInfo `xml:"ChangeInfo"`
}
return xmlResp(http.StatusOK, response{})
return xmlResp(http.StatusOK, response{
ChangeInfo: xmlChangeInfo{
Id: generateID(),
Status: "PENDING",
SubmittedAt: time.Now().UTC().Format(time.RFC3339),
},
})
}

// --- Traffic Policy Instance handlers ---
Expand Down Expand Up @@ -1804,21 +1809,20 @@ func (p *Provider) createCidrCollection(req *http.Request) (*plugin.Response, er
return nil, err
}
type xmlCidrCollection struct {
XMLName xml.Name `xml:"CidrCollection"`
CidrCollectionId string `xml:"CidrCollectionId"`
Name string `xml:"Name"`
State string `xml:"State"`
Id string `xml:"Id"`
Name string `xml:"Name"`
Version int `xml:"Version"`
}
type response struct {
XMLName xml.Name `xml:"CreateCidrCollectionResponse"`
CidrCollection xmlCidrCollection `xml:"CidrCollection"`
Location string `xml:"Location"`
XMLName xml.Name `xml:"CreateCidrCollectionResponse"`
Collection xmlCidrCollection `xml:"Collection"`
Location string `xml:"Location"`
}
return xmlResp(http.StatusCreated, response{
CidrCollection: xmlCidrCollection{
CidrCollectionId: ccID,
Name: in.Name,
State: "Created",
Collection: xmlCidrCollection{
Id: ccID,
Name: in.Name,
Version: 1,
},
Location: fmt.Sprintf("/2013-04-01/cidrcollection/%s", ccID),
})
Expand Down Expand Up @@ -1852,9 +1856,8 @@ func (p *Provider) listCidrCollections(_ *http.Request) (*plugin.Response, error
return nil, err
}
type xmlCidrCollection struct {
CidrCollectionId string `xml:"CidrCollectionId"`
Name string `xml:"Name"`
State string `xml:"State"`
Id string `xml:"Id"`
Name string `xml:"Name"`
}
type response struct {
XMLName xml.Name `xml:"ListCidrCollectionsResponse"`
Expand All @@ -1866,9 +1869,8 @@ func (p *Provider) listCidrCollections(_ *http.Request) (*plugin.Response, error
resp := response{IsTruncated: false, MaxItems: 100}
for _, cc := range ccList {
resp.CidrCollections = append(resp.CidrCollections, xmlCidrCollection{
CidrCollectionId: cc.CidrCollectionID,
Name: cc.Name,
State: cc.State,
Id: cc.CidrCollectionID,
Name: cc.Name,
})
}
return xmlResp(http.StatusOK, resp)
Expand All @@ -1894,7 +1896,10 @@ func (p *Provider) listCidrBlocks(_ *http.Request) (*plugin.Response, error) {

func (p *Provider) listCidrLocations(_ *http.Request) (*plugin.Response, error) {
type response struct {
XMLName xml.Name `xml:"ListCidrLocationsResponse"`
XMLName xml.Name `xml:"ListCidrLocationsResponse"`
CidrLocations []struct {
LocationName string `xml:"LocationName"`
} `xml:"CidrLocations>CidrLocation"`
}
return xmlResp(http.StatusOK, response{})
}
Expand Down Expand Up @@ -1951,14 +1956,10 @@ func (p *Provider) createReusableDelegationSet(req *http.Request) (*plugin.Respo
if err := p.store.CreateReusableDelegationSet(ds); err != nil {
return nil, err
}
type xmlNameServer struct {
NameServer string `xml:"NameServer"`
}
type xmlDelegationSet struct {
DelegationSetId string `xml:"DelegationSetId"`
Name string `xml:"Name"`
State string `xml:"State"`
NameServers xmlNameServer `xml:"NameServers"`
Id string `xml:"Id"`
CallerReference string `xml:"CallerReference"`
NameServers []string `xml:"NameServers>NameServer"`
}
type response struct {
XMLName xml.Name `xml:"CreateReusableDelegationSetResponse"`
Expand All @@ -1967,10 +1968,9 @@ func (p *Provider) createReusableDelegationSet(req *http.Request) (*plugin.Respo
}
return xmlResp(http.StatusCreated, response{
DelegationSet: xmlDelegationSet{
DelegationSetId: dsID,
Name: in.Name,
State: "Complete",
NameServers: xmlNameServer{NameServer: "ns-1.devcloud.internal"},
Id: dsID,
CallerReference: "rds-ref-1",
NameServers: []string{"ns-1.devcloud.internal", "ns-2.devcloud.internal"},
},
Location: fmt.Sprintf("/2013-04-01/delegationset/%s", dsID),
})
Expand All @@ -1988,28 +1988,20 @@ func (p *Provider) getReusableDelegationSet(req *http.Request) (*plugin.Response
}
return nil, err
}
type xmlNameServer struct {
NameServer string `xml:"NameServer"`
}
type xmlDelegationSet struct {
DelegationSetId string `xml:"DelegationSetId"`
Name string `xml:"Name"`
State string `xml:"State"`
NameServers []xmlNameServer `xml:"NameServers>NameServer"`
Id string `xml:"Id"`
CallerReference string `xml:"CallerReference"`
NameServers []string `xml:"NameServers>NameServer"`
}
type response struct {
XMLName xml.Name `xml:"GetReusableDelegationSetResponse"`
DelegationSet xmlDelegationSet `xml:"DelegationSet"`
}
return xmlResp(http.StatusOK, response{
DelegationSet: xmlDelegationSet{
DelegationSetId: ds.DelegationSetID,
Name: ds.Name,
State: ds.State,
NameServers: []xmlNameServer{
{NameServer: "ns-1.devcloud.internal"},
{NameServer: "ns-2.devcloud.internal"},
},
Id: ds.DelegationSetID,
CallerReference: "rds-ref-1",
NameServers: []string{"ns-1.devcloud.internal", "ns-2.devcloud.internal"},
},
})
}
Expand All @@ -2019,31 +2011,23 @@ func (p *Provider) listReusableDelegationSets(_ *http.Request) (*plugin.Response
if err != nil {
return nil, err
}
type xmlNameServer struct {
NameServer string `xml:"NameServer"`
}
type xmlDelegationSet struct {
DelegationSetId string `xml:"DelegationSetId"`
Name string `xml:"Name"`
State string `xml:"State"`
NameServers []xmlNameServer `xml:"NameServers>NameServer"`
Id string `xml:"Id"`
CallerReference string `xml:"CallerReference"`
NameServers []string `xml:"NameServers>NameServer"`
}
type response struct {
XMLName xml.Name `xml:"ListReusableDelegationSetsResponse"`
DelegationSets []xmlDelegationSet `xml:"ReusableDelegationSets>ReusableDelegationSet"`
DelegationSets []xmlDelegationSet `xml:"DelegationSets>DelegationSet"`
IsTruncated bool `xml:"IsTruncated"`
MaxItems int `xml:"MaxItems"`
NextId string `xml:"NextDelegationSetId"`
MaxItems string `xml:"MaxItems"`
}
resp := response{IsTruncated: false, MaxItems: 100}
resp := response{IsTruncated: false, MaxItems: "100"}
for _, ds := range dsList {
resp.DelegationSets = append(resp.DelegationSets, xmlDelegationSet{
DelegationSetId: ds.DelegationSetID,
Name: ds.Name,
State: ds.State,
NameServers: []xmlNameServer{
{NameServer: "ns-1.devcloud.internal"},
},
Id: ds.DelegationSetID,
CallerReference: "rds-ref-1",
NameServers: []string{"ns-1.devcloud.internal", "ns-2.devcloud.internal"},
})
}
return xmlResp(http.StatusOK, resp)
Expand Down
23 changes: 12 additions & 11 deletions internal/services/route53/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,14 +389,14 @@ func TestCidrCollectionHandlers(t *testing.T) {
assert.Equal(t, http.StatusCreated, resp.StatusCode)

var createResp struct {
CidrCollection struct {
CidrCollectionId string `xml:"CidrCollectionId"`
State string `xml:"State"`
} `xml:"CidrCollection"`
Collection struct {
Id string `xml:"Id"`
Name string `xml:"Name"`
} `xml:"Collection"`
}
require.NoError(t, xml.Unmarshal(resp.Body, &createResp))
ccID := createResp.CidrCollection.CidrCollectionId
assert.Equal(t, "Created", createResp.CidrCollection.State)
ccID := createResp.Collection.Id
assert.Equal(t, "my-cidr-collection", createResp.Collection.Name)

// ListCidrCollections
req = httptest.NewRequest(http.MethodGet, "/2013-04-01/cidrcollection", nil)
Expand Down Expand Up @@ -444,13 +444,14 @@ func TestReusableDelegationSetHandlers(t *testing.T) {

var createResp struct {
DelegationSet struct {
DelegationSetId string `xml:"DelegationSetId"`
State string `xml:"State"`
Id string `xml:"Id"`
CallerReference string `xml:"CallerReference"`
NameServers []string `xml:"NameServers>NameServer"`
} `xml:"DelegationSet"`
}
require.NoError(t, xml.Unmarshal(resp.Body, &createResp))
dsID := createResp.DelegationSet.DelegationSetId
assert.Equal(t, "Complete", createResp.DelegationSet.State)
dsID := createResp.DelegationSet.Id
assert.Equal(t, "rds-ref-1", createResp.DelegationSet.CallerReference)

// GetReusableDelegationSet
req = httptest.NewRequest(http.MethodGet, "/2013-04-01/delegationset/"+dsID, nil)
Expand All @@ -464,7 +465,7 @@ func TestReusableDelegationSetHandlers(t *testing.T) {
resp, err = p.HandleRequest(context.Background(), "ListReusableDelegationSets", req)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Contains(t, string(resp.Body), "my-delegation-set")
assert.Contains(t, string(resp.Body), dsID)

// DeleteReusableDelegationSet
req = httptest.NewRequest(http.MethodDelete, "/2013-04-01/delegationset/"+dsID, nil)
Expand Down
Loading
Loading