Skip to content

Commit 4ab40e9

Browse files
committed
add userdata resource and datasource
1 parent 790a6a0 commit 4ab40e9

File tree

2 files changed

+297
-0
lines changed

2 files changed

+297
-0
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
//
2+
// Licensed to the Apache Software Foundation (ASF) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The ASF licenses this file
6+
// to you under the Apache License, Version 2.0 (the
7+
// "License"); you may not use this file except in compliance
8+
// with the License. You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing,
13+
// software distributed under the License is distributed on an
14+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
// KIND, either express or implied. See the License for the
16+
// specific language governing permissions and limitations
17+
// under the License.
18+
//
19+
20+
package cloudstack
21+
22+
import (
23+
"encoding/base64"
24+
"fmt"
25+
"log"
26+
27+
"github.com/apache/cloudstack-go/v2/cloudstack"
28+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
29+
)
30+
31+
func dataSourceCloudstackUserData() *schema.Resource {
32+
return &schema.Resource{
33+
Read: dataSourceCloudstackUserDataRead,
34+
Schema: map[string]*schema.Schema{
35+
"name": {
36+
Type: schema.TypeString,
37+
Required: true,
38+
},
39+
"account": {
40+
Type: schema.TypeString,
41+
Computed: true,
42+
},
43+
"account_id": {
44+
Type: schema.TypeString,
45+
Computed: true,
46+
},
47+
"domain": {
48+
Type: schema.TypeString,
49+
Computed: true,
50+
},
51+
"domain_id": {
52+
Type: schema.TypeString,
53+
Computed: true,
54+
},
55+
"project": {
56+
Type: schema.TypeString,
57+
Computed: true,
58+
},
59+
"project_id": {
60+
Type: schema.TypeString,
61+
Computed: true,
62+
},
63+
"userdata_id": {
64+
Type: schema.TypeString,
65+
Computed: true,
66+
},
67+
"userdata": {
68+
Type: schema.TypeString,
69+
Computed: true,
70+
},
71+
"params": {
72+
Type: schema.TypeString,
73+
Computed: true,
74+
},
75+
},
76+
}
77+
}
78+
79+
func dataSourceCloudstackUserDataRead(d *schema.ResourceData, meta interface{}) error {
80+
cs := meta.(*cloudstack.CloudStackClient)
81+
82+
name := d.Get("name").(string)
83+
p := cs.User.NewListUserDataParams()
84+
p.SetName(name)
85+
86+
if v, ok := d.GetOk("account"); ok {
87+
p.SetAccount(v.(string))
88+
}
89+
if v, ok := d.GetOk("domain_id"); ok {
90+
p.SetDomainid(v.(string))
91+
}
92+
93+
log.Printf("[DEBUG] Listing user data with name: %s", name)
94+
userdataList, err := cs.User.ListUserData(p)
95+
if err != nil {
96+
return fmt.Errorf("Error listing user data with name %s: %s", name, err)
97+
}
98+
99+
if len(userdataList.UserData) == 0 {
100+
return fmt.Errorf("No user data found with name: %s", name)
101+
}
102+
if len(userdataList.UserData) > 1 {
103+
return fmt.Errorf("Multiple user data entries found with name: %s", name)
104+
}
105+
106+
userdata := userdataList.UserData[0]
107+
108+
d.SetId(userdata.Id)
109+
d.Set("name", userdata.Name)
110+
d.Set("account", userdata.Account)
111+
d.Set("account_id", userdata.Accountid)
112+
d.Set("domain", userdata.Domain)
113+
d.Set("domain_id", userdata.Domainid)
114+
d.Set("userdata_id", userdata.Id)
115+
d.Set("params", userdata.Params)
116+
117+
if userdata.Project != "" {
118+
d.Set("project", userdata.Project)
119+
d.Set("project_id", userdata.Projectid)
120+
}
121+
122+
if userdata.Userdata != "" {
123+
decoded, err := base64.StdEncoding.DecodeString(userdata.Userdata)
124+
if err != nil {
125+
d.Set("userdata", userdata.Userdata) // Fallback: use raw data
126+
} else {
127+
d.Set("userdata", decoded)
128+
}
129+
}
130+
return nil
131+
}
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
//
2+
// Licensed to the Apache Software Foundation (ASF) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The ASF licenses this file
6+
// to you under the Apache License, Version 2.0 (the
7+
// "License"); you may not use this file except in compliance
8+
// with the License. You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing,
13+
// software distributed under the License is distributed on an
14+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
// KIND, either express or implied. See the License for the
16+
// specific language governing permissions and limitations
17+
// under the License.
18+
//
19+
20+
package cloudstack
21+
22+
import (
23+
"fmt"
24+
"strings"
25+
26+
"github.com/apache/cloudstack-go/v2/cloudstack"
27+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
28+
)
29+
30+
func resourceCloudStackUserData() *schema.Resource {
31+
return &schema.Resource{
32+
Create: resourceCloudStackUserDataCreate,
33+
Read: resourceCloudStackUserDataRead,
34+
Delete: resourceCloudStackUserDataDelete,
35+
Importer: &schema.ResourceImporter{
36+
State: importStatePassthrough,
37+
},
38+
39+
Schema: map[string]*schema.Schema{
40+
"name": {
41+
Type: schema.TypeString,
42+
Required: true,
43+
ForceNew: true,
44+
Description: "Name of the user data",
45+
},
46+
47+
"userdata": {
48+
Type: schema.TypeString,
49+
Required: true,
50+
ForceNew: true,
51+
Description: "The user data content to be registered",
52+
},
53+
54+
"account": {
55+
Type: schema.TypeString,
56+
Optional: true,
57+
ForceNew: true,
58+
Description: "An optional account for the user data. Must be used with domain_id.",
59+
},
60+
61+
"domain_id": {
62+
Type: schema.TypeString,
63+
Optional: true,
64+
ForceNew: true,
65+
Description: "An optional domain ID for the user data. If the account parameter is used, domain_id must also be used.",
66+
},
67+
68+
"params": {
69+
Type: schema.TypeSet,
70+
Optional: true,
71+
ForceNew: true,
72+
Description: "Optional comma separated list of variables declared in user data content.",
73+
Elem: &schema.Schema{
74+
Type: schema.TypeString,
75+
},
76+
},
77+
78+
"project_id": {
79+
Type: schema.TypeString,
80+
Optional: true,
81+
ForceNew: true,
82+
Description: "An optional project for the user data.",
83+
},
84+
},
85+
}
86+
}
87+
88+
func resourceCloudStackUserDataCreate(d *schema.ResourceData, meta interface{}) error {
89+
cs := meta.(*cloudstack.CloudStackClient)
90+
91+
p := cs.User.NewRegisterUserDataParams(d.Get("name").(string), d.Get("userdata").(string))
92+
if v, ok := d.GetOk("account"); ok {
93+
p.SetAccount(v.(string))
94+
}
95+
if v, ok := d.GetOk("domain_id"); ok {
96+
p.SetDomainid(v.(string))
97+
}
98+
if v, ok := d.GetOk("project_id"); ok {
99+
p.SetProjectid(v.(string))
100+
}
101+
if v, ok := d.GetOk("params"); ok {
102+
paramsList := v.(*schema.Set).List()
103+
var params []string
104+
for _, param := range paramsList {
105+
params = append(params, param.(string))
106+
}
107+
p.SetParams(strings.Join(params, ","))
108+
}
109+
110+
userdata, err := cs.User.RegisterUserData(p)
111+
if err != nil {
112+
return fmt.Errorf("Error registering user data: %s", err)
113+
}
114+
115+
d.SetId(userdata.Id)
116+
117+
return resourceCloudStackUserDataRead(d, meta)
118+
}
119+
120+
func resourceCloudStackUserDataRead(d *schema.ResourceData, meta interface{}) error {
121+
cs := meta.(*cloudstack.CloudStackClient)
122+
123+
id := d.Id()
124+
125+
p := cs.User.NewListUserDataParams()
126+
p.SetId(id)
127+
128+
userdata, err := cs.User.ListUserData(p)
129+
if err != nil {
130+
return fmt.Errorf("Error retrieving user data with ID %s: %s", id, err)
131+
}
132+
133+
d.Set("name", userdata.UserData[0].Name)
134+
d.Set("userdata", userdata.UserData[0])
135+
if d.Get("account").(string) != "" {
136+
d.Set("account", userdata.UserData[0].Account)
137+
}
138+
if d.Get("domain_id").(string) != "" {
139+
d.Set("domain_id", userdata.UserData[0].Domainid)
140+
}
141+
if userdata.UserData[0].Params != "" {
142+
paramsList := strings.Split(userdata.UserData[0].Params, ",")
143+
var paramsSet []interface{}
144+
for _, param := range paramsList {
145+
paramsSet = append(paramsSet, param)
146+
}
147+
d.Set("params", schema.NewSet(schema.HashString, paramsSet))
148+
}
149+
if userdata.UserData[0].Projectid != "" {
150+
d.Set("project_id", userdata.UserData[0].Projectid)
151+
}
152+
153+
return nil
154+
}
155+
156+
func resourceCloudStackUserDataDelete(d *schema.ResourceData, meta interface{}) error {
157+
cs := meta.(*cloudstack.CloudStackClient)
158+
159+
p := cs.User.NewDeleteUserDataParams(d.Id())
160+
_, err := cs.User.DeleteUserData(p)
161+
if err != nil {
162+
return fmt.Errorf("Error deleting user data with ID %s: %s", d.Id(), err)
163+
}
164+
165+
return nil
166+
}

0 commit comments

Comments
 (0)