Skip to content

Commit bc40f7d

Browse files
authored
Merge pull request #44 from IBM/prajwal-jarali-202509160923
Unification of Data format for API response and Bootstrap file
2 parents ce794e7 + 7645e98 commit bc40f7d

File tree

9 files changed

+107
-162
lines changed

9 files changed

+107
-162
lines changed

.secrets.baseline

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"files": "^.secrets.baseline$|go.sum|vendor|.cra/.cveignore",
44
"lines": null
55
},
6-
"generated_at": "2025-04-30T06:02:48Z",
6+
"generated_at": "2025-09-16T09:24:28Z",
77
"plugins_used": [
88
{
99
"name": "AWSKeyDetector"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# IBM Cloud App Configuration Go server SDK 0.5.7
1+
# IBM Cloud App Configuration Go server SDK 0.5.8
22

33
IBM Cloud App Configuration SDK is used to perform feature flag and property evaluation based on the configuration on
44
IBM Cloud App Configuration service.

examples/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.23.0
55
toolchain go1.23.7
66

77
require (
8-
github.com/IBM/appconfiguration-go-sdk v0.5.7
8+
github.com/IBM/appconfiguration-go-sdk v0.5.8
99
github.com/gorilla/mux v1.8.0
1010
github.com/joho/godotenv v1.5.1
1111
)

lib/ConfigurationHandler.go

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,10 @@ func (ch *ConfigurationHandler) loadData() {
104104
log.Info(messages.ReadPersistentCache, path)
105105
ch.persistentData = utils.ReadFiles(path)
106106
if !bytes.Equal(ch.persistentData, []byte(`{}`)) {
107-
configurations := models.ExtractConfigurationsFromPersistentCache(ch.persistentData)
108-
if configurations != nil {
107+
configurations, err := models.ExtractConfigurations(ch.persistentData, ch.environmentID, ch.collectionID)
108+
if err != nil {
109+
log.Error("Error occurred while reading persistent cache configurations - ", err.Error())
110+
} else {
109111
ch.saveInCache(configurations)
110112
persistentCacheRead = true
111113
}
@@ -116,17 +118,22 @@ func (ch *ConfigurationHandler) loadData() {
116118
if len(ch.persistentCacheDirectory) > 0 {
117119
if !persistentCacheRead {
118120
bootstrapFileData := utils.ReadFiles(path)
119-
bootstrapConfigurations := models.ExtractConfigurationsFromBootstrapJson(bootstrapFileData, ch.collectionID, ch.environmentID)
120-
if bootstrapConfigurations != nil {
121+
bootstrapConfigurations, err := models.ExtractConfigurations(bootstrapFileData, ch.environmentID, ch.collectionID)
122+
if err != nil {
123+
log.Error("Error occurred while reading bootstrap configurations - ", err.Error())
124+
} else {
121125
ch.saveInCache(bootstrapConfigurations)
122-
go utils.StoreFiles(string(models.FormatConfig(bootstrapConfigurations, ch.environmentID)), ch.persistentCacheDirectory)
126+
go utils.StoreFiles(string(models.FormatConfig(bootstrapConfigurations, ch.environmentID, ch.collectionID)), ch.persistentCacheDirectory)
127+
123128
}
124129
}
125130
} else {
126131
log.Info(messages.ReadBootstrapConfigurations, path)
127132
bootstrapFileData := utils.ReadFiles(path)
128-
bootstrapConfigurations := models.ExtractConfigurationsFromBootstrapJson(bootstrapFileData, ch.collectionID, ch.environmentID)
129-
if bootstrapConfigurations != nil {
133+
bootstrapConfigurations, err := models.ExtractConfigurations(bootstrapFileData, ch.environmentID, ch.collectionID)
134+
if err != nil {
135+
log.Error("Error occurred while reading bootstrap configurations - ", err.Error())
136+
} else {
130137
ch.saveInCache(bootstrapConfigurations)
131138
}
132139
}
@@ -147,7 +154,7 @@ func (ch *ConfigurationHandler) FetchConfigurationData() {
147154
func (ch *ConfigurationHandler) saveInCache(data []byte) {
148155
ch.mu.Lock()
149156
defer ch.mu.Unlock()
150-
configurations := models.Configurations{}
157+
configurations := models.CacheConfig{}
151158
err := json.Unmarshal(data, &configurations)
152159
if err != nil {
153160
log.Error(messages.UnmarshalJSONErr, err)
@@ -156,12 +163,12 @@ func (ch *ConfigurationHandler) saveInCache(data []byte) {
156163
log.Debug(configurations)
157164
featureMap := make(map[string]models.Feature)
158165
for _, feature := range configurations.Features {
159-
featureMap[feature.GetFeatureID()] = feature
166+
featureMap[feature.GetFeatureID()] = feature.Feature
160167
}
161168

162169
propertyMap := make(map[string]models.Property)
163170
for _, property := range configurations.Properties {
164-
propertyMap[property.GetPropertyID()] = property
171+
propertyMap[property.GetPropertyID()] = property.Property
165172
}
166173

167174
segmentMap := make(map[string]models.Segment)
@@ -230,8 +237,9 @@ func (ch *ConfigurationHandler) fetchFromAPI() {
230237
if response != nil && response.StatusCode == 200 {
231238
log.Info(messages.FetchAPISuccessful)
232239
jsonData, _ := json.Marshal(response.Result)
233-
configurations := models.ExtractConfigurationsFromAPIResponse(jsonData)
234-
if configurations == nil {
240+
configurations, err := models.ExtractConfigurations(jsonData, ch.environmentID, ch.collectionID)
241+
if err != nil {
242+
log.Error("Error occurred while reading fetched configurations - ", err.Error())
235243
return
236244
}
237245
// asynchronously write the response to persistent volume, if enabled

lib/configurationhandler_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func TestFetchApi(t *testing.T) {
8686
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
8787
w.Header().Set("Content-type", "application/json")
8888
w.WriteHeader(200)
89-
fmt.Fprintf(w, "%s", `{ "environments": [ { "name": "Dev", "environment_id": "dev", "description": "Environment created on instance creation", "tags": "", "color_code": "#FDD13A", "features": [ { "name": "Cycle Rentals", "feature_id": "cycle-rentals", "type": "BOOLEAN", "enabled_value": true, "disabled_value": false, "segment_rules": [], "enabled": true, "rollout_percentage": 95 } ], "properties": [ { "name": "Show Ad", "property_id": "show-ad", "tags": "", "type": "BOOLEAN", "value": false, "segment_rules": [] } ] } ], "segments": [ { "name": "beta-users", "segment_id": "knliu818", "rules": [ { "values": [ "ibm.com" ], "operator": "contains", "attribute_name": "email" } ] }, { "name": "ibm employees", "segment_id": "ka761hap", "rules": [ { "values": [ "ibm.com", "in.ibm.com" ], "operator": "endsWith", "attribute_name": "email" } ] } ] }`)
89+
fmt.Fprintf(w, "%s", `{ "environments": [ { "name": "Dev", "environment_id": "dev", "description": "Environment created on instance creation", "tags": "", "color_code": "#FDD13A", "features": [ { "name": "Cycle Rentals", "feature_id": "cycle-rentals", "type": "BOOLEAN", "enabled_value": true, "disabled_value": false, "segment_rules": [], "enabled": true, "rollout_percentage": 95 } ], "properties": [ { "name": "Show Ad", "property_id": "show-ad", "tags": "", "type": "BOOLEAN", "value": false, "segment_rules": [ { "order": 1, "rollout_percentage": 100, "rules": [ { "segments": [ "knliu818", "ka761hap" ] } ], "value": true } ] } ] } ], "collections": [ { "name": "C1", "collection_id": "c1" } ], "segments": [ { "name": "beta-users", "segment_id": "knliu818", "rules": [ { "values": [ "ibm.com" ], "operator": "contains", "attribute_name": "email" } ] }, { "name": "ibm employees", "segment_id": "ka761hap", "rules": [ { "values": [ "ibm.com", "in.ibm.com" ], "operator": "endsWith", "attribute_name": "email" } ] } ] }`)
9090
}))
9191

9292
ch := GetConfigurationHandlerInstance()

lib/internal/constants/constants.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const DefaultEntityID = "$$null$$"
2626
const DefaultUsageLimit = 10
2727

2828
// UserAgent specifies the user agent name
29-
const UserAgent = "appconfiguration-go-sdk/0.5.7"
29+
const UserAgent = "appconfiguration-go-sdk/0.5.8"
3030

3131
// ConfigurationFile : Name of file to which configurations will be written
3232
const ConfigurationFile = "appconfiguration.json"

lib/internal/models/Config.go

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,47 +16,35 @@
1616

1717
package models
1818

19-
// Configurations : all the configurations pulled out from bootstrapJson/persistentCache/GitConfig/APIResponse
19+
// CacheConfig : all the configurations pulled out from bootstrapJson/persistentCache/GitConfig/APIResponse
2020
// will be stored in this struct format.
21-
type Configurations struct {
22-
Features []Feature `json:"features"`
23-
Properties []Property `json:"properties"`
24-
Segments []Segment `json:"segments"`
21+
type CacheConfig struct {
22+
Features []FeatureC `json:"features"`
23+
Properties []PropertyC `json:"properties"`
24+
Segments []Segment `json:"segments"`
2525
}
2626

27-
// BootstrapConfig : the format of bootstrap configurations.
28-
type BootstrapConfig struct {
29-
Environments []EnvironmentC `json:"environments"`
30-
Collections []Collection `json:"collections"`
31-
Segments []Segment `json:"segments"`
27+
// Config : the format of all configurations.
28+
type Config struct {
29+
Environments []Environment `json:"environments"`
30+
Collections []Collection `json:"collections"`
31+
Segments []Segment `json:"segments"`
3232
}
33-
type EnvironmentC struct {
33+
type Environment struct {
3434
Name string `json:"name"`
3535
EnvironmentID string `json:"environment_id"`
3636
Features []FeatureC `json:"features"`
3737
Properties []PropertyC `json:"properties"`
3838
}
3939
type Collection struct {
40-
Name string `json:"name"`
40+
Name string `json:"name,omitempty"`
4141
CollectionID string `json:"collection_id"`
4242
}
4343
type FeatureC struct {
4444
Feature
45-
Collections []Collection `json:"collections"`
45+
Collections []Collection `json:"collections,omitempty"`
4646
}
4747
type PropertyC struct {
4848
Property
49-
Collections []Collection `json:"collections"`
50-
}
51-
52-
// APIConfig : the format of configurations returned from the API: `GET /config?action=sdkConfig`
53-
type APIConfig struct {
54-
Environments []Environment `json:"environments"`
55-
Segments []Segment `json:"segments"`
56-
}
57-
type Environment struct {
58-
Name string `json:"name"`
59-
EnvironmentID string `json:"environment_id"`
60-
Features []Feature `json:"features"`
61-
Properties []Property `json:"properties"`
49+
Collections []Collection `json:"collections,omitempty"`
6250
}

0 commit comments

Comments
 (0)