Skip to content

Commit ba22257

Browse files
authored
GO SDK 12.4.0 Release
GO SDK 12.4.0 Release
2 parents f6f0b48 + c22a900 commit ba22257

32 files changed

+725
-32
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](http://keepachangelog.com/)
66

7+
## 12.4.0 - 2019-11-12
8+
### Added
9+
- Support for access to APEX and SQL Dev features on autonomous transaction processing and autonomous data warehouse resources in the Database service
10+
- Support for registering / deregistering autonomous transaction processing and autonomous data warehouse resources with Data Safe in the Database service
11+
- Support for redirecting HTTP / HTTPS request URIs to different URIs in the Load Balancing service
12+
- Support for specifying compartments on options APIs in the Container Engine for Kubernetes service
13+
- Support for volume performance units on block volumes in the Block Storage service
14+
- Support for opc-multipart-md5 verification for UploadManager. Example can be found on [Github](https://github.com/oracle/oci-go-sdk/blob/v8.0.0/example/example_objectstorage_test.go#L57)
15+
716
## 12.3.0 - 2019-11-05
817
### Added
918
- Support for the Analytics Cloud service

common/version.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

containerengine/get_cluster_options_request_response.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ type GetClusterOptionsRequest struct {
1414
// The id of the option set to retrieve. Only "all" is supported.
1515
ClusterOptionId *string `mandatory:"true" contributesTo:"path" name:"clusterOptionId"`
1616

17+
// The OCID of the compartment.
18+
CompartmentId *string `mandatory:"false" contributesTo:"query" name:"compartmentId"`
19+
1720
// Unique Oracle-assigned identifier for the request. If you need to contact
1821
// Oracle about a particular request, please provide the request ID.
1922
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`

containerengine/get_node_pool_options_request_response.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ type GetNodePoolOptionsRequest struct {
1414
// The id of the option set to retrieve. Use "all" get all options, or use a cluster ID to get options specific to the provided cluster.
1515
NodePoolOptionId *string `mandatory:"true" contributesTo:"path" name:"nodePoolOptionId"`
1616

17+
// The OCID of the compartment.
18+
CompartmentId *string `mandatory:"false" contributesTo:"query" name:"compartmentId"`
19+
1720
// Unique Oracle-assigned identifier for the request. If you need to contact
1821
// Oracle about a particular request, please provide the request ID.
1922
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`

containerengine/node_pool_options.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ type NodePoolOptions struct {
2020
// Available Kubernetes versions.
2121
KubernetesVersions []string `mandatory:"false" json:"kubernetesVersions"`
2222

23-
// Available image names.
24-
Images []string `mandatory:"false" json:"images"`
25-
2623
// Available shapes for nodes.
2724
Shapes []string `mandatory:"false" json:"shapes"`
25+
26+
// Available image names.
27+
Images []string `mandatory:"false" json:"images"`
2828
}
2929

3030
func (m NodePoolOptions) String() string {

core/boot_volume.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ type BootVolume struct {
7070
// Specifies whether the boot volume's data has finished copying from the source boot volume or boot volume backup.
7171
IsHydrated *bool `mandatory:"false" json:"isHydrated"`
7272

73+
// The number of Volume Performance Units that will be applied to this boot volume per GB.
74+
VpusPerGB *int64 `mandatory:"false" json:"vpusPerGB"`
75+
7376
// The size of the boot volume in GBs.
7477
SizeInGBs *int64 `mandatory:"false" json:"sizeInGBs"`
7578

@@ -97,6 +100,7 @@ func (m *BootVolume) UnmarshalJSON(data []byte) (e error) {
97100
FreeformTags map[string]string `json:"freeformTags"`
98101
ImageId *string `json:"imageId"`
99102
IsHydrated *bool `json:"isHydrated"`
103+
VpusPerGB *int64 `json:"vpusPerGB"`
100104
SizeInGBs *int64 `json:"sizeInGBs"`
101105
SourceDetails bootvolumesourcedetails `json:"sourceDetails"`
102106
VolumeGroupId *string `json:"volumeGroupId"`
@@ -119,6 +123,7 @@ func (m *BootVolume) UnmarshalJSON(data []byte) (e error) {
119123
m.FreeformTags = model.FreeformTags
120124
m.ImageId = model.ImageId
121125
m.IsHydrated = model.IsHydrated
126+
m.VpusPerGB = model.VpusPerGB
122127
m.SizeInGBs = model.SizeInGBs
123128
nn, e := model.SourceDetails.UnmarshalPolymorphicJSON(model.SourceDetails.JsonData)
124129
if e != nil {

core/create_boot_volume_details.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ type CreateBootVolumeDetails struct {
5454

5555
// The size of the volume in GBs.
5656
SizeInGBs *int64 `mandatory:"false" json:"sizeInGBs"`
57+
58+
// The number of Volume Performance Units that will be applied to this boot volume per GB.
59+
VpusPerGB *int64 `mandatory:"false" json:"vpusPerGB"`
5760
}
5861

5962
func (m CreateBootVolumeDetails) String() string {
@@ -69,6 +72,7 @@ func (m *CreateBootVolumeDetails) UnmarshalJSON(data []byte) (e error) {
6972
FreeformTags map[string]string `json:"freeformTags"`
7073
KmsKeyId *string `json:"kmsKeyId"`
7174
SizeInGBs *int64 `json:"sizeInGBs"`
75+
VpusPerGB *int64 `json:"vpusPerGB"`
7276
AvailabilityDomain *string `json:"availabilityDomain"`
7377
CompartmentId *string `json:"compartmentId"`
7478
SourceDetails bootvolumesourcedetails `json:"sourceDetails"`
@@ -84,6 +88,7 @@ func (m *CreateBootVolumeDetails) UnmarshalJSON(data []byte) (e error) {
8488
m.FreeformTags = model.FreeformTags
8589
m.KmsKeyId = model.KmsKeyId
8690
m.SizeInGBs = model.SizeInGBs
91+
m.VpusPerGB = model.VpusPerGB
8792
m.AvailabilityDomain = model.AvailabilityDomain
8893
m.CompartmentId = model.CompartmentId
8994
nn, e := model.SourceDetails.UnmarshalPolymorphicJSON(model.SourceDetails.JsonData)

core/create_volume_details.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ type CreateVolumeDetails struct {
4848
// The OCID of the KMS key to be used as the master encryption key for the volume.
4949
KmsKeyId *string `mandatory:"false" json:"kmsKeyId"`
5050

51+
// The number of Volume Performance Units that will be applied to this volume per GB.
52+
VpusPerGB *int64 `mandatory:"false" json:"vpusPerGB"`
53+
5154
// The size of the volume in GBs.
5255
SizeInGBs *int64 `mandatory:"false" json:"sizeInGBs"`
5356

@@ -78,6 +81,7 @@ func (m *CreateVolumeDetails) UnmarshalJSON(data []byte) (e error) {
7881
DisplayName *string `json:"displayName"`
7982
FreeformTags map[string]string `json:"freeformTags"`
8083
KmsKeyId *string `json:"kmsKeyId"`
84+
VpusPerGB *int64 `json:"vpusPerGB"`
8185
SizeInGBs *int64 `json:"sizeInGBs"`
8286
SizeInMBs *int64 `json:"sizeInMBs"`
8387
SourceDetails volumesourcedetails `json:"sourceDetails"`
@@ -95,6 +99,7 @@ func (m *CreateVolumeDetails) UnmarshalJSON(data []byte) (e error) {
9599
m.DisplayName = model.DisplayName
96100
m.FreeformTags = model.FreeformTags
97101
m.KmsKeyId = model.KmsKeyId
102+
m.VpusPerGB = model.VpusPerGB
98103
m.SizeInGBs = model.SizeInGBs
99104
m.SizeInMBs = model.SizeInMBs
100105
nn, e := model.SourceDetails.UnmarshalPolymorphicJSON(model.SourceDetails.JsonData)

core/update_boot_volume_details.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ type UpdateBootVolumeDetails struct {
3535

3636
// The size to resize the volume to in GBs. Has to be larger than the current size.
3737
SizeInGBs *int64 `mandatory:"false" json:"sizeInGBs"`
38+
39+
// The number of Volume Performance Units that will be applied to this boot volume per GB.
40+
VpusPerGB *int64 `mandatory:"false" json:"vpusPerGB"`
3841
}
3942

4043
func (m UpdateBootVolumeDetails) String() string {

core/update_volume_details.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ type UpdateVolumeDetails struct {
3333
// Example: `{"Department": "Finance"}`
3434
FreeformTags map[string]string `mandatory:"false" json:"freeformTags"`
3535

36+
// The number of Volume Performance Units that will be applied to this volume per GB.
37+
VpusPerGB *int64 `mandatory:"false" json:"vpusPerGB"`
38+
3639
// The size to resize the volume to in GBs. Has to be larger than the current size.
3740
SizeInGBs *int64 `mandatory:"false" json:"sizeInGBs"`
3841
}

core/volume.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ type Volume struct {
7070
// The OCID of the KMS key which is the master encryption key for the volume.
7171
KmsKeyId *string `mandatory:"false" json:"kmsKeyId"`
7272

73+
// The number of Volume Performance Units that will be applied to this volume per GB.
74+
VpusPerGB *int64 `mandatory:"false" json:"vpusPerGB"`
75+
7376
// The size of the volume in GBs.
7477
SizeInGBs *int64 `mandatory:"false" json:"sizeInGBs"`
7578

@@ -93,6 +96,7 @@ func (m *Volume) UnmarshalJSON(data []byte) (e error) {
9396
SystemTags map[string]map[string]interface{} `json:"systemTags"`
9497
IsHydrated *bool `json:"isHydrated"`
9598
KmsKeyId *string `json:"kmsKeyId"`
99+
VpusPerGB *int64 `json:"vpusPerGB"`
96100
SizeInGBs *int64 `json:"sizeInGBs"`
97101
SourceDetails volumesourcedetails `json:"sourceDetails"`
98102
VolumeGroupId *string `json:"volumeGroupId"`
@@ -114,6 +118,7 @@ func (m *Volume) UnmarshalJSON(data []byte) (e error) {
114118
m.SystemTags = model.SystemTags
115119
m.IsHydrated = model.IsHydrated
116120
m.KmsKeyId = model.KmsKeyId
121+
m.VpusPerGB = model.VpusPerGB
117122
m.SizeInGBs = model.SizeInGBs
118123
nn, e := model.SourceDetails.UnmarshalPolymorphicJSON(model.SourceDetails.JsonData)
119124
if e != nil {

database/autonomous_database.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ type AutonomousDatabase struct {
9999

100100
// Indicates if auto scaling is enabled for the Autonomous Database CPU core count. Note that auto scaling is available for serverless deployments (https://docs.cloud.oracle.com/Content/Database/Concepts/adboverview.htm#AEI) only.
101101
IsAutoScalingEnabled *bool `mandatory:"false" json:"isAutoScalingEnabled"`
102+
103+
// Status of the Data Safe registration for this Autonomous Database.
104+
DataSafeStatus AutonomousDatabaseDataSafeStatusEnum `mandatory:"false" json:"dataSafeStatus,omitempty"`
102105
}
103106

104107
func (m AutonomousDatabase) String() string {
@@ -199,3 +202,32 @@ func GetAutonomousDatabaseDbWorkloadEnumValues() []AutonomousDatabaseDbWorkloadE
199202
}
200203
return values
201204
}
205+
206+
// AutonomousDatabaseDataSafeStatusEnum Enum with underlying type: string
207+
type AutonomousDatabaseDataSafeStatusEnum string
208+
209+
// Set of constants representing the allowable values for AutonomousDatabaseDataSafeStatusEnum
210+
const (
211+
AutonomousDatabaseDataSafeStatusRegistering AutonomousDatabaseDataSafeStatusEnum = "REGISTERING"
212+
AutonomousDatabaseDataSafeStatusRegistered AutonomousDatabaseDataSafeStatusEnum = "REGISTERED"
213+
AutonomousDatabaseDataSafeStatusDeregistering AutonomousDatabaseDataSafeStatusEnum = "DEREGISTERING"
214+
AutonomousDatabaseDataSafeStatusNotRegistered AutonomousDatabaseDataSafeStatusEnum = "NOT_REGISTERED"
215+
AutonomousDatabaseDataSafeStatusFailed AutonomousDatabaseDataSafeStatusEnum = "FAILED"
216+
)
217+
218+
var mappingAutonomousDatabaseDataSafeStatus = map[string]AutonomousDatabaseDataSafeStatusEnum{
219+
"REGISTERING": AutonomousDatabaseDataSafeStatusRegistering,
220+
"REGISTERED": AutonomousDatabaseDataSafeStatusRegistered,
221+
"DEREGISTERING": AutonomousDatabaseDataSafeStatusDeregistering,
222+
"NOT_REGISTERED": AutonomousDatabaseDataSafeStatusNotRegistered,
223+
"FAILED": AutonomousDatabaseDataSafeStatusFailed,
224+
}
225+
226+
// GetAutonomousDatabaseDataSafeStatusEnumValues Enumerates the set of values for AutonomousDatabaseDataSafeStatusEnum
227+
func GetAutonomousDatabaseDataSafeStatusEnumValues() []AutonomousDatabaseDataSafeStatusEnum {
228+
values := make([]AutonomousDatabaseDataSafeStatusEnum, 0)
229+
for _, v := range mappingAutonomousDatabaseDataSafeStatus {
230+
values = append(values, v)
231+
}
232+
return values
233+
}

database/autonomous_database_connection_urls.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ type AutonomousDatabaseConnectionUrls struct {
2121

2222
// Oracle Application Express (APEX) URL.
2323
ApexUrl *string `mandatory:"false" json:"apexUrl"`
24+
25+
// Oracle Machine Learning User Management URL.
26+
MachineLearningUserManagementUrl *string `mandatory:"false" json:"machineLearningUserManagementUrl"`
2427
}
2528

2629
func (m AutonomousDatabaseConnectionUrls) String() string {

database/autonomous_database_summary.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ type AutonomousDatabaseSummary struct {
100100

101101
// Indicates if auto scaling is enabled for the Autonomous Database CPU core count. Note that auto scaling is available for serverless deployments (https://docs.cloud.oracle.com/Content/Database/Concepts/adboverview.htm#AEI) only.
102102
IsAutoScalingEnabled *bool `mandatory:"false" json:"isAutoScalingEnabled"`
103+
104+
// Status of the Data Safe registration for this Autonomous Database.
105+
DataSafeStatus AutonomousDatabaseSummaryDataSafeStatusEnum `mandatory:"false" json:"dataSafeStatus,omitempty"`
103106
}
104107

105108
func (m AutonomousDatabaseSummary) String() string {
@@ -200,3 +203,32 @@ func GetAutonomousDatabaseSummaryDbWorkloadEnumValues() []AutonomousDatabaseSumm
200203
}
201204
return values
202205
}
206+
207+
// AutonomousDatabaseSummaryDataSafeStatusEnum Enum with underlying type: string
208+
type AutonomousDatabaseSummaryDataSafeStatusEnum string
209+
210+
// Set of constants representing the allowable values for AutonomousDatabaseSummaryDataSafeStatusEnum
211+
const (
212+
AutonomousDatabaseSummaryDataSafeStatusRegistering AutonomousDatabaseSummaryDataSafeStatusEnum = "REGISTERING"
213+
AutonomousDatabaseSummaryDataSafeStatusRegistered AutonomousDatabaseSummaryDataSafeStatusEnum = "REGISTERED"
214+
AutonomousDatabaseSummaryDataSafeStatusDeregistering AutonomousDatabaseSummaryDataSafeStatusEnum = "DEREGISTERING"
215+
AutonomousDatabaseSummaryDataSafeStatusNotRegistered AutonomousDatabaseSummaryDataSafeStatusEnum = "NOT_REGISTERED"
216+
AutonomousDatabaseSummaryDataSafeStatusFailed AutonomousDatabaseSummaryDataSafeStatusEnum = "FAILED"
217+
)
218+
219+
var mappingAutonomousDatabaseSummaryDataSafeStatus = map[string]AutonomousDatabaseSummaryDataSafeStatusEnum{
220+
"REGISTERING": AutonomousDatabaseSummaryDataSafeStatusRegistering,
221+
"REGISTERED": AutonomousDatabaseSummaryDataSafeStatusRegistered,
222+
"DEREGISTERING": AutonomousDatabaseSummaryDataSafeStatusDeregistering,
223+
"NOT_REGISTERED": AutonomousDatabaseSummaryDataSafeStatusNotRegistered,
224+
"FAILED": AutonomousDatabaseSummaryDataSafeStatusFailed,
225+
}
226+
227+
// GetAutonomousDatabaseSummaryDataSafeStatusEnumValues Enumerates the set of values for AutonomousDatabaseSummaryDataSafeStatusEnum
228+
func GetAutonomousDatabaseSummaryDataSafeStatusEnumValues() []AutonomousDatabaseSummaryDataSafeStatusEnum {
229+
values := make([]AutonomousDatabaseSummaryDataSafeStatusEnum, 0)
230+
for _, v := range mappingAutonomousDatabaseSummaryDataSafeStatus {
231+
values = append(values, v)
232+
}
233+
return values
234+
}

database/database_client.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,48 @@ func (client DatabaseClient) deleteVmClusterNetwork(ctx context.Context, request
15061506
return response, err
15071507
}
15081508

1509+
// DeregisterAutonomousDatabaseDataSafe Asynchronously deregisters Data Safe for this Autonomous Database.
1510+
func (client DatabaseClient) DeregisterAutonomousDatabaseDataSafe(ctx context.Context, request DeregisterAutonomousDatabaseDataSafeRequest) (response DeregisterAutonomousDatabaseDataSafeResponse, err error) {
1511+
var ociResponse common.OCIResponse
1512+
policy := common.NoRetryPolicy()
1513+
if request.RetryPolicy() != nil {
1514+
policy = *request.RetryPolicy()
1515+
}
1516+
ociResponse, err = common.Retry(ctx, request, client.deregisterAutonomousDatabaseDataSafe, policy)
1517+
if err != nil {
1518+
if ociResponse != nil {
1519+
response = DeregisterAutonomousDatabaseDataSafeResponse{RawResponse: ociResponse.HTTPResponse()}
1520+
}
1521+
return
1522+
}
1523+
if convertedResponse, ok := ociResponse.(DeregisterAutonomousDatabaseDataSafeResponse); ok {
1524+
response = convertedResponse
1525+
} else {
1526+
err = fmt.Errorf("failed to convert OCIResponse into DeregisterAutonomousDatabaseDataSafeResponse")
1527+
}
1528+
return
1529+
}
1530+
1531+
// deregisterAutonomousDatabaseDataSafe implements the OCIOperation interface (enables retrying operations)
1532+
func (client DatabaseClient) deregisterAutonomousDatabaseDataSafe(ctx context.Context, request common.OCIRequest) (common.OCIResponse, error) {
1533+
httpRequest, err := request.HTTPRequest(http.MethodPost, "/autonomousDatabases/{autonomousDatabaseId}/actions/deregisterDataSafe")
1534+
if err != nil {
1535+
return nil, err
1536+
}
1537+
1538+
var response DeregisterAutonomousDatabaseDataSafeResponse
1539+
var httpResponse *http.Response
1540+
httpResponse, err = client.Call(ctx, &httpRequest)
1541+
defer common.CloseBodyIfValid(httpResponse)
1542+
response.RawResponse = httpResponse
1543+
if err != nil {
1544+
return response, err
1545+
}
1546+
1547+
err = common.UnmarshalResponse(httpResponse, &response)
1548+
return response, err
1549+
}
1550+
15091551
// DownloadExadataInfrastructureConfigFile Downloads the configuration file for the specified Exadata infrastructure.
15101552
func (client DatabaseClient) DownloadExadataInfrastructureConfigFile(ctx context.Context, request DownloadExadataInfrastructureConfigFileRequest) (response DownloadExadataInfrastructureConfigFileResponse, err error) {
15111553
var ociResponse common.OCIResponse
@@ -4025,6 +4067,48 @@ func (client DatabaseClient) listVmClusters(ctx context.Context, request common.
40254067
return response, err
40264068
}
40274069

4070+
// RegisterAutonomousDatabaseDataSafe Asynchronously registers Data Safe with this Autonomous Database.
4071+
func (client DatabaseClient) RegisterAutonomousDatabaseDataSafe(ctx context.Context, request RegisterAutonomousDatabaseDataSafeRequest) (response RegisterAutonomousDatabaseDataSafeResponse, err error) {
4072+
var ociResponse common.OCIResponse
4073+
policy := common.NoRetryPolicy()
4074+
if request.RetryPolicy() != nil {
4075+
policy = *request.RetryPolicy()
4076+
}
4077+
ociResponse, err = common.Retry(ctx, request, client.registerAutonomousDatabaseDataSafe, policy)
4078+
if err != nil {
4079+
if ociResponse != nil {
4080+
response = RegisterAutonomousDatabaseDataSafeResponse{RawResponse: ociResponse.HTTPResponse()}
4081+
}
4082+
return
4083+
}
4084+
if convertedResponse, ok := ociResponse.(RegisterAutonomousDatabaseDataSafeResponse); ok {
4085+
response = convertedResponse
4086+
} else {
4087+
err = fmt.Errorf("failed to convert OCIResponse into RegisterAutonomousDatabaseDataSafeResponse")
4088+
}
4089+
return
4090+
}
4091+
4092+
// registerAutonomousDatabaseDataSafe implements the OCIOperation interface (enables retrying operations)
4093+
func (client DatabaseClient) registerAutonomousDatabaseDataSafe(ctx context.Context, request common.OCIRequest) (common.OCIResponse, error) {
4094+
httpRequest, err := request.HTTPRequest(http.MethodPost, "/autonomousDatabases/{autonomousDatabaseId}/actions/registerDataSafe")
4095+
if err != nil {
4096+
return nil, err
4097+
}
4098+
4099+
var response RegisterAutonomousDatabaseDataSafeResponse
4100+
var httpResponse *http.Response
4101+
httpResponse, err = client.Call(ctx, &httpRequest)
4102+
defer common.CloseBodyIfValid(httpResponse)
4103+
response.RawResponse = httpResponse
4104+
if err != nil {
4105+
return response, err
4106+
}
4107+
4108+
err = common.UnmarshalResponse(httpResponse, &response)
4109+
return response, err
4110+
}
4111+
40284112
// ReinstateDataGuardAssociation Reinstates the database identified by the `databaseId` parameter into the standby role in a Data Guard association.
40294113
func (client DatabaseClient) ReinstateDataGuardAssociation(ctx context.Context, request ReinstateDataGuardAssociationRequest) (response ReinstateDataGuardAssociationResponse, err error) {
40304114
var ociResponse common.OCIResponse

0 commit comments

Comments
 (0)