github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/openstack/db/v1/instances/requests.go (about)

     1  package instances
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/vnpaycloud-console/gophercloud/v2"
     7  	db "github.com/vnpaycloud-console/gophercloud/v2/openstack/db/v1/databases"
     8  	"github.com/vnpaycloud-console/gophercloud/v2/openstack/db/v1/users"
     9  	"github.com/vnpaycloud-console/gophercloud/v2/pagination"
    10  )
    11  
    12  // CreateOptsBuilder is the top-level interface for create options.
    13  type CreateOptsBuilder interface {
    14  	ToInstanceCreateMap() (map[string]any, error)
    15  }
    16  
    17  // DatastoreOpts represents the configuration for how an instance stores data.
    18  type DatastoreOpts struct {
    19  	Version string `json:"version"`
    20  	Type    string `json:"type"`
    21  }
    22  
    23  // ToMap converts a DatastoreOpts to a map[string]string (for a request body)
    24  func (opts DatastoreOpts) ToMap() (map[string]any, error) {
    25  	return gophercloud.BuildRequestBody(opts, "")
    26  }
    27  
    28  // NetworkOpts is used within CreateOpts to control a new server's network attachments.
    29  type NetworkOpts struct {
    30  	// UUID of a nova-network to attach to the newly provisioned server.
    31  	// Required unless Port is provided.
    32  	UUID string `json:"net-id,omitempty"`
    33  
    34  	// Port of a neutron network to attach to the newly provisioned server.
    35  	// Required unless UUID is provided.
    36  	Port string `json:"port-id,omitempty"`
    37  
    38  	// V4FixedIP [optional] specifies a fixed IPv4 address to be used on this network.
    39  	V4FixedIP string `json:"v4-fixed-ip,omitempty"`
    40  
    41  	// V6FixedIP [optional] specifies a fixed IPv6 address to be used on this network.
    42  	V6FixedIP string `json:"v6-fixed-ip,omitempty"`
    43  }
    44  
    45  // ToMap converts a NetworkOpts to a map[string]string (for a request body)
    46  func (opts NetworkOpts) ToMap() (map[string]any, error) {
    47  	return gophercloud.BuildRequestBody(opts, "")
    48  }
    49  
    50  // CreateOpts is the struct responsible for configuring a new database instance.
    51  type CreateOpts struct {
    52  	// The availability zone of the instance.
    53  	AvailabilityZone string `json:"availability_zone,omitempty"`
    54  	// ID of the configuration group that you want to attach to the instance.
    55  	Configuration string `json:"configuration,omitempty"`
    56  	// Either the integer UUID (in string form) of the flavor, or its URI
    57  	// reference as specified in the response from the List() call. Required.
    58  	FlavorRef string
    59  	// Specifies the volume size in gigabytes (GB). The value must be between 1
    60  	// and 300. Required.
    61  	Size int
    62  	// Specifies the volume type.
    63  	VolumeType string
    64  	// Name of the instance to create. The length of the name is limited to
    65  	// 255 characters and any characters are permitted. Optional.
    66  	Name string
    67  	// A slice of database information options.
    68  	Databases db.CreateOptsBuilder
    69  	// A slice of user information options.
    70  	Users users.CreateOptsBuilder
    71  	// Options to configure the type of datastore the instance will use. This is
    72  	// optional, and if excluded will default to MySQL.
    73  	Datastore *DatastoreOpts
    74  	// Networks dictates how this server will be attached to available networks.
    75  	Networks []NetworkOpts
    76  }
    77  
    78  // ToInstanceCreateMap will render a JSON map.
    79  func (opts CreateOpts) ToInstanceCreateMap() (map[string]any, error) {
    80  	if opts.Size > 300 || opts.Size < 1 {
    81  		err := gophercloud.ErrInvalidInput{}
    82  		err.Argument = "instances.CreateOpts.Size"
    83  		err.Value = opts.Size
    84  		err.Info = "Size (GB) must be between 1-300"
    85  		return nil, err
    86  	}
    87  
    88  	if opts.FlavorRef == "" {
    89  		return nil, gophercloud.ErrMissingInput{Argument: "instances.CreateOpts.FlavorRef"}
    90  	}
    91  
    92  	instance := map[string]any{
    93  		"flavorRef": opts.FlavorRef,
    94  	}
    95  
    96  	if opts.AvailabilityZone != "" {
    97  		instance["availability_zone"] = opts.AvailabilityZone
    98  	}
    99  
   100  	if opts.Configuration != "" {
   101  		instance["configuration"] = opts.Configuration
   102  	}
   103  
   104  	if opts.Name != "" {
   105  		instance["name"] = opts.Name
   106  	}
   107  	if opts.Databases != nil {
   108  		dbs, err := opts.Databases.ToDBCreateMap()
   109  		if err != nil {
   110  			return nil, err
   111  		}
   112  		instance["databases"] = dbs["databases"]
   113  	}
   114  	if opts.Users != nil {
   115  		users, err := opts.Users.ToUserCreateMap()
   116  		if err != nil {
   117  			return nil, err
   118  		}
   119  		instance["users"] = users["users"]
   120  	}
   121  	if opts.Datastore != nil {
   122  		datastore, err := opts.Datastore.ToMap()
   123  		if err != nil {
   124  			return nil, err
   125  		}
   126  		instance["datastore"] = datastore
   127  	}
   128  
   129  	if len(opts.Networks) > 0 {
   130  		networks := make([]map[string]any, len(opts.Networks))
   131  		for i, net := range opts.Networks {
   132  			var err error
   133  			networks[i], err = net.ToMap()
   134  			if err != nil {
   135  				return nil, err
   136  			}
   137  		}
   138  		instance["nics"] = networks
   139  	}
   140  
   141  	volume := map[string]any{
   142  		"size": opts.Size,
   143  	}
   144  
   145  	if opts.VolumeType != "" {
   146  		volume["type"] = opts.VolumeType
   147  	}
   148  
   149  	instance["volume"] = volume
   150  
   151  	return map[string]any{"instance": instance}, nil
   152  }
   153  
   154  // Create asynchronously provisions a new database instance. It requires the
   155  // user to specify a flavor and a volume size. The API service then provisions
   156  // the instance with the requested flavor and sets up a volume of the specified
   157  // size, which is the storage for the database instance.
   158  //
   159  // Although this call only allows the creation of 1 instance per request, you
   160  // can create an instance with multiple databases and users. The default
   161  // binding for a MySQL instance is port 3306.
   162  func Create(ctx context.Context, client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
   163  	b, err := opts.ToInstanceCreateMap()
   164  	if err != nil {
   165  		r.Err = err
   166  		return
   167  	}
   168  	resp, err := client.Post(ctx, baseURL(client), &b, &r.Body, &gophercloud.RequestOpts{OkCodes: []int{200}})
   169  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   170  	return
   171  }
   172  
   173  // List retrieves the status and information for all database instances.
   174  func List(client *gophercloud.ServiceClient) pagination.Pager {
   175  	return pagination.NewPager(client, baseURL(client), func(r pagination.PageResult) pagination.Page {
   176  		return InstancePage{pagination.LinkedPageBase{PageResult: r}}
   177  	})
   178  }
   179  
   180  // Get retrieves the status and information for a specified database instance.
   181  func Get(ctx context.Context, client *gophercloud.ServiceClient, id string) (r GetResult) {
   182  	resp, err := client.Get(ctx, resourceURL(client, id), &r.Body, nil)
   183  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   184  	return
   185  }
   186  
   187  // Delete permanently destroys the database instance.
   188  func Delete(ctx context.Context, client *gophercloud.ServiceClient, id string) (r DeleteResult) {
   189  	resp, err := client.Delete(ctx, resourceURL(client, id), nil)
   190  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   191  	return
   192  }
   193  
   194  // EnableRootUser enables the login from any host for the root user and
   195  // provides the user with a generated root password.
   196  func EnableRootUser(ctx context.Context, client *gophercloud.ServiceClient, id string) (r EnableRootUserResult) {
   197  	resp, err := client.Post(ctx, userRootURL(client, id), nil, &r.Body, &gophercloud.RequestOpts{OkCodes: []int{200}})
   198  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   199  	return
   200  }
   201  
   202  // IsRootEnabled checks an instance to see if root access is enabled. It returns
   203  // True if root user is enabled for the specified database instance or False
   204  // otherwise.
   205  func IsRootEnabled(ctx context.Context, client *gophercloud.ServiceClient, id string) (r IsRootEnabledResult) {
   206  	resp, err := client.Get(ctx, userRootURL(client, id), &r.Body, nil)
   207  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   208  	return
   209  }
   210  
   211  // Restart will restart only the MySQL Instance. Restarting MySQL will
   212  // erase any dynamic configuration settings that you have made within MySQL.
   213  // The MySQL service will be unavailable until the instance restarts.
   214  func Restart(ctx context.Context, client *gophercloud.ServiceClient, id string) (r ActionResult) {
   215  	b := map[string]any{"restart": struct{}{}}
   216  	resp, err := client.Post(ctx, actionURL(client, id), &b, nil, nil)
   217  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   218  	return
   219  }
   220  
   221  // Resize changes the memory size of the instance, assuming a valid
   222  // flavorRef is provided. It will also restart the MySQL service.
   223  func Resize(ctx context.Context, client *gophercloud.ServiceClient, id, flavorRef string) (r ActionResult) {
   224  	b := map[string]any{"resize": map[string]string{"flavorRef": flavorRef}}
   225  	resp, err := client.Post(ctx, actionURL(client, id), &b, nil, nil)
   226  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   227  	return
   228  }
   229  
   230  // ResizeVolume will resize the attached volume for an instance. It supports
   231  // only increasing the volume size and does not support decreasing the size.
   232  // The volume size is in gigabytes (GB) and must be an integer.
   233  func ResizeVolume(ctx context.Context, client *gophercloud.ServiceClient, id string, size int) (r ActionResult) {
   234  	b := map[string]any{"resize": map[string]any{"volume": map[string]int{"size": size}}}
   235  	resp, err := client.Post(ctx, actionURL(client, id), &b, nil, nil)
   236  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   237  	return
   238  }
   239  
   240  // AttachConfigurationGroup will attach configuration group to the instance
   241  func AttachConfigurationGroup(ctx context.Context, client *gophercloud.ServiceClient, instanceID string, configID string) (r ConfigurationResult) {
   242  	b := map[string]any{"instance": map[string]any{"configuration": configID}}
   243  	resp, err := client.Put(ctx, resourceURL(client, instanceID), &b, nil, &gophercloud.RequestOpts{OkCodes: []int{202}})
   244  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   245  	return
   246  }
   247  
   248  // DetachConfigurationGroup will dettach configuration group from the instance
   249  func DetachConfigurationGroup(ctx context.Context, client *gophercloud.ServiceClient, instanceID string) (r ConfigurationResult) {
   250  	b := map[string]any{"instance": map[string]any{}}
   251  	resp, err := client.Put(ctx, resourceURL(client, instanceID), &b, nil, &gophercloud.RequestOpts{OkCodes: []int{202}})
   252  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   253  	return
   254  }