I have the hostname
and a json
formated string. I want to insert the hostname
inside the value string of a key in that json
formated string.
My full code:
func pager() string {
token := "xxxxxxxxxxx"
url := "https://api.pagerduty.com/incidents"
hostname, err := os.Hostname()
fmt.Println(hostname, err)
jsonStr := []byte(`{
"incident": {
"type": "incident",
**"title": "Docker is down on."+hostname,**
"service": {
"id": "PWIXJZS",
"type": "service_reference"
},
"priority": {
"id": "P53ZZH5",
"type": "priority_reference"
},
"urgency": "high",
"incident_key": "baf7cf21b1da41b4b0221008339ff357",
"body": {
"type": "incident_body",
"details": "A disk is getting full on this machine. You should investigate what is causing the disk to fill, and ensure that there is an automated process in place for ensuring data is rotated (eg. logs should have logrotate around them). If data is expected to stay on this disk forever, you should start planning to scale up to a larger disk."
},
"escalation_policy": {
"id": "PT20YPA",
"type": "escalation_policy_reference"
}
}
}`)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/vnd.pagerduty+json;version=2")
req.Header.Set("From", "shinoda@wathever.com")
req.Header.Set("Authorization", "Token token="+token)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
return resp.Status
}
func main() {
fmt.Println(pager())
}
I am not very familiar with go, in python I can do this easily and I dont know the proper way to do this in golang.
If someone could explain me, I would be grateful.
thanks in advance.
make a struct in go to represent the json
type
Incident struct {
Type string `json:"type"`
Title string `json:"title"`
Service struct {
ID string `json:"id"`
Type string `json:"type"`
} `json:"service"`
Priority struct {
ID string `json:"id"`
Type string `json:"type"`
} `json:"priority"`
Urgency string `json:"urgency"`
IncidentKey string `json:"incident_key"`
Body struct {
Type string `json:"type"`
Details string `json:"details"`
} `json:"body"`
EscalationPolicy struct {
ID string `json:"id"`
Type string `json:"type"`
} `json:"escalation_policy"`
}
then do something like
hostname,err:=os.Hostname()
if (err !=nil) {
panic(err)
}
incident:=Incident{ Type: "incident",
Title: fmt.Sprintf("Docker is down on %s", hostname),
//...etc etc add all other fields
req, err := http.NewRequest("POST", url, json.Marshal(incident))
The workaround for declaring structs inside structs seems a bit clumsy (sorry)
Service: struct {
ID string `json:"id"`
Type string `json:"type"`
}{
ID: "asdf",
Type: "ABC",
},
This other answer https://stackoverflow.com/a/53255390/1153938 shows how to split the structs inside the Incident struct and is a cleaner way of doing it
I'll leave this answer here because it might be of interest how to declare it in this way
If you are only calling json.Unmarshal
then this way would be fine but for declaring stuff in a program as you need to do, perhaps not the best
The problem is as simple as properly quoting strings. This should solve your immediate problem:
jsonStr := []byte(`{
"incident": {
"type": "incident",
"title": "Docker is down on `+hostname+`",
"service": {
"id": "PWIXJZS",
"type": "service_reference"
},
"priority": {
"id": "P53ZZH5",
"type": "priority_reference"
},
"urgency": "high",
"incident_key": "baf7cf21b1da41b4b0221008339ff357",
"body": {
"type": "incident_body",
"details": "A disk is getting full on this machine. You should investigate what is causing the disk to fill, and ensure that there is an automated process in place for ensuring data is rotated (eg. logs should have logrotate around them). If data is expected to stay on this disk forever, you should start planning to scale up to a larger disk."
},
"escalation_policy": {
"id": "PT20YPA",
"type": "escalation_policy_reference"
}
}
}`)
But a much better approach, as suggested by @Vorsprung, is to use a proper Go data structure, and marshal it to JSON.
Try this solution:
hostname, err := os.Hostname()
if err != nil {
// handle err
}
indent := fmt.Sprintf(`{
"incident": {
"type": "incident",
"title": "Docker is down on %s",
"service": {
"id": "PWIXJZS",
"type": "service_reference"
},
"priority": {
"id": "P53ZZH5",
"type": "priority_reference"
},
"urgency": "high",
"incident_key": "baf7cf21b1da41b4b0221008339ff357",
"body": {
"type": "incident_body",
"details": "A disk is getting full on this machine. You should investigate what is causing the disk to fill, and ensure that there is an automated process in place for ensuring data is rotated (eg. logs should have logrotate around them). If data is expected to stay on this disk forever, you should start planning to scale up to a larger disk."
},
"escalation_policy": {
"id": "PT20YPA",
"type": "escalation_policy_reference"
}
}
}`, hostname)
jsonStr := []byte(indent)
Building on @Vorsprung's response, unless I'm mistaken you may want to define the structs a little differently to avoid the error you are getting based on your response Once you've initialized and populated required properties on incident you should be able to POST the object after performing a json.Marshal() on the object.
jsonObject, _ := json.MarshalIndent(someIncident, "", "\t")
If the structs are to be used outside of this package you may want to change the names to uppercase to allow exportability.
type incident struct {
Type string `json:"type"`
Title string `json:"title"`
Service service `json:"service"`
Priority priority `json:"priority"`
Urgency string `json:"urgency"`
IncidentKey string `json:"incident_key"`
Body body `json:"body"`
EscalationPolicy escalationPolicy `json:"escalation_policy"`
}
type service struct {
ID string `json:"id"`
Type string `json:"type"`
}
type priority struct {
ID string `json:"id"`
Type string `json:"type"`
}
type body struct {
Type string `json:"type"`
Details string `json:"details"`
}
type escalationPolicy struct {
ID string `json:"id"`
Type string `json:"type"`
}
Initialization of the object:
someIncident := incident{
Type: "SomeType",
Title: "SomeTitle",
Service: service{
ID: "SomeId",
Type: "SomeType"},
Priority: priority{
ID: "SomeId",
Type: "SomeType"},
Urgency: "SomeUrgency",
IncidentKey: "SomeKey",
Body: body{
Type: "SomeType",
Details: "SomeDetails"},
EscalationPolicy: escalationPolicy{
ID: "SomeId",
Type: "SomeType"}}