package VM::HetznerCloud::API::Servers;

# ABSTRACT: Servers

# ---
# This class is auto-generated by bin/get_hetzner_info.pl
# ---

use v5.24;

use Moo;
use Types::Standard qw(:all);

use Mojo::Base -strict, -signatures;

extends 'VM::HetznerCloud::APIBase';

with 'MooX::Singleton';

use VM::HetznerCloud::Schema;

our $VERSION = '0.0.1'; # VERSION

has endpoint  => ( is => 'ro', isa => Str, default => sub { 'servers' } );

sub list ($self, %params) {
    my $request_params = {
        'label_selector' => {
            'in'       => 'query',
            'required' => 0,
            'validate' => 'string',
        },
        'name' => {
            'in'       => 'query',
            'required' => 0,
            'validate' => 'string',
        },
        'sort' => {
            'in'       => 'query',
            'required' => 0,
            'validate' => 'string',
        },
        'status' => {
            'in'       => 'query',
            'required' => 0,
            'validate' => 'string',
        },
    };
;
    return $self->_request( '', \%params, $request_params, { type => 'get' } );
}

sub create ($self, %params) {
    my $request_params = {};
    return $self->_request( '', \%params, $request_params, { type => 'post' } );
}

sub delete ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id', \%params, $request_params, { type => 'delete' } );
}

sub get ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id', \%params, $request_params, { type => 'get' } );
}

sub put ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id', \%params, $request_params, { type => 'put' } );
}

sub list_actions ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
        'sort' => {
            'in'       => 'query',
            'required' => 0,
            'validate' => 'string',
        },
        'status' => {
            'in'       => 'query',
            'required' => 0,
            'validate' => 'string',
        },
    };
;
    return $self->_request( '/:id/actions', \%params, $request_params, { type => 'get' } );
}

sub create_actions_add_to_placement_group ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/add_to_placement_group', \%params, $request_params, { type => 'post' } );
}

sub create_actions_attach_iso ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/attach_iso', \%params, $request_params, { type => 'post' } );
}

sub create_actions_attach_to_network ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/attach_to_network', \%params, $request_params, { type => 'post' } );
}

sub create_actions_change_alias_ips ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/change_alias_ips', \%params, $request_params, { type => 'post' } );
}

sub create_actions_change_dns_ptr ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/change_dns_ptr', \%params, $request_params, { type => 'post' } );
}

sub create_actions_change_protection ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/change_protection', \%params, $request_params, { type => 'post' } );
}

sub create_actions_change_type ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/change_type', \%params, $request_params, { type => 'post' } );
}

sub create_actions_create_image ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/create_image', \%params, $request_params, { type => 'post' } );
}

sub create_actions_detach_from_network ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/detach_from_network', \%params, $request_params, { type => 'post' } );
}

sub create_actions_detach_iso ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/detach_iso', \%params, $request_params, { type => 'post' } );
}

sub create_actions_disable_backup ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/disable_backup', \%params, $request_params, { type => 'post' } );
}

sub create_actions_disable_rescue ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/disable_rescue', \%params, $request_params, { type => 'post' } );
}

sub create_actions_enable_backup ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/enable_backup', \%params, $request_params, { type => 'post' } );
}

sub create_actions_enable_rescue ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/enable_rescue', \%params, $request_params, { type => 'post' } );
}

sub create_actions_poweroff ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/poweroff', \%params, $request_params, { type => 'post' } );
}

sub create_actions_poweron ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/poweron', \%params, $request_params, { type => 'post' } );
}

sub create_actions_reboot ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/reboot', \%params, $request_params, { type => 'post' } );
}

sub create_actions_rebuild ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/rebuild', \%params, $request_params, { type => 'post' } );
}

sub create_actions_remove_from_placement_group ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/remove_from_placement_group', \%params, $request_params, { type => 'post' } );
}

sub create_actions_request_console ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/request_console', \%params, $request_params, { type => 'post' } );
}

sub create_actions_reset ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/reset', \%params, $request_params, { type => 'post' } );
}

sub create_actions_reset_password ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/reset_password', \%params, $request_params, { type => 'post' } );
}

sub create_actions_shutdown ($self, %params) {
    my $request_params = {
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/shutdown', \%params, $request_params, { type => 'post' } );
}

sub get_actions ($self, %params) {
    my $request_params = {
        'action_id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
    };
;
    return $self->_request( '/:id/actions/:action_id', \%params, $request_params, { type => 'get' } );
}

sub list_metrics ($self, %params) {
    my $request_params = {
        'end' => {
            'in'       => 'query',
            'required' => 1,
            'validate' => 'string',
        },
        'id' => {
            'in'       => 'path',
            'required' => 1,
            'validate' => 'int64',
        },
        'start' => {
            'in'       => 'query',
            'required' => 1,
            'validate' => 'string',
        },
        'step' => {
            'in'       => 'query',
            'required' => 0,
            'validate' => 'string',
        },
        'type' => {
            'in'       => 'query',
            'required' => 1,
            'validate' => 'string',
        },
    };
;
    return $self->_request( '/:id/metrics', \%params, $request_params, { type => 'get' } );
}


1;

__END__

=pod

=encoding UTF-8

=head1 NAME

VM::HetznerCloud::API::Servers - Servers

=head1 VERSION

version 0.0.1

=head1 SYNOPSIS

    use VM::HetznerCloud;

    my $api_key = '1234abc';
    my $cloud   = VM::HetznerCloud->new(
        token => $api_key,
    );

    $cloud->records->create(
    );

=head1 ATTRIBUTES

=over 4

=item * endpoint

=back

=head1 METHODS

=head2 list

Returns all existing Server objects

    $cloud->servers->list(
        label_selector => 'test',
        name => 'test',
        sort => 'test',
        status => 'test',
    );

=head2 create

Creates a new Server. Returns preliminary information about the Server as well as an Action that covers progress of creation.

    $cloud->servers->create();

=head2 delete

Deletes a Server. This immediately removes the Server from your account, and it is no longer accessible.

    $cloud->servers->delete(
        id => 'test',
    );

=head2 get

Returns a specific Server object. The Server must exist inside the Project

    $cloud->servers->get(
        id => 'test',
    );

=head2 put

Updates a Server. You can update a Server’s name and a Server’s labels.
Please note that Server names must be unique per Project and valid hostnames as per RFC 1123 (i.e. may only contain letters, digits, periods, and dashes).
Also note that when updating labels, the Server’s current set of labels will be replaced with the labels provided in the request body. So, for example, if you want to add a new label, you have to provide all existing labels plus the new label in the request body.

    $cloud->servers->put(
        id => 'test',
    );

=head2 list_actions

Returns all Action objects for a Server. You can `sort` the results by using the sort URI parameter, and filter them with the `status` parameter.

    $cloud->servers->list_actions(
        id => 'test',
        sort => 'test',
        status => 'test',
    );

=head2 create_actions_add_to_placement_group

Adds a Server to a Placement Group.

Server must be powered off for this command to succeed.

#### Call specific error codes

| Code                          | Description                                                          |
|-------------------------------|----------------------------------------------------------------------|
| `server_not_stopped`          | The action requires a stopped server                                 |

    $cloud->servers->create_actions_add_to_placement_group(
        id => 'test',
    );

=head2 create_actions_attach_iso

Attaches an ISO to a Server. The Server will immediately see it as a new disk. An already attached ISO will automatically be detached before the new ISO is attached.

Servers with attached ISOs have a modified boot order: They will try to boot from the ISO first before falling back to hard disk.

    $cloud->servers->create_actions_attach_iso(
        id => 'test',
    );

=head2 create_actions_attach_to_network

Attaches a Server to a network. This will complement the fixed public Server interface by adding an additional ethernet interface to the Server which is connected to the specified network.

The Server will get an IP auto assigned from a subnet of type `server` in the same `network_zone`.

Using the `alias_ips` attribute you can also define one or more additional IPs to the Servers. Please note that you will have to configure these IPs by hand on your Server since only the primary IP will be given out by DHCP.

**Call specific error codes**

| Code                             | Description                                                           |
|----------------------------------|-----------------------------------------------------------------------|
| `server_already_attached`        | The server is already attached to the network                         |
| `ip_not_available`               | The provided Network IP is not available                              |
| `no_subnet_available`            | No Subnet or IP is available for the Server within the network        |
| `networks_overlap`               | The network IP range overlaps with one of the server networks         |

    $cloud->servers->create_actions_attach_to_network(
        id => 'test',
    );

=head2 create_actions_change_alias_ips

Changes the alias IPs of an already attached Network. Note that the existing aliases for the specified Network will be replaced with these provided in the request body. So if you want to add an alias IP, you have to provide the existing ones from the Network plus the new alias IP in the request body.

    $cloud->servers->create_actions_change_alias_ips(
        id => 'test',
    );

=head2 create_actions_change_dns_ptr

Changes the hostname that will appear when getting the hostname belonging to the primary IPs (IPv4 and IPv6) of this Server.

Floating IPs assigned to the Server are not affected by this.

    $cloud->servers->create_actions_change_dns_ptr(
        id => 'test',
    );

=head2 create_actions_change_protection

Changes the protection configuration of the Server.

    $cloud->servers->create_actions_change_protection(
        id => 'test',
    );

=head2 create_actions_change_type

Changes the type (Cores, RAM and disk sizes) of a Server.

Server must be powered off for this command to succeed.

This copies the content of its disk, and starts it again.

You can only migrate to Server types with the same `storage_type` and equal or bigger disks. Shrinking disks is not possible as it might destroy data.

If the disk gets upgraded, the Server type can not be downgraded any more. If you plan to downgrade the Server type, set `upgrade_disk` to `false`.

#### Call specific error codes

| Code                          | Description                                                          |
|-------------------------------|----------------------------------------------------------------------|
| `invalid_server_type`         | The server type does not fit for the given server or is deprecated   |
| `server_not_stopped`          | The action requires a stopped server                                 |

    $cloud->servers->create_actions_change_type(
        id => 'test',
    );

=head2 create_actions_create_image

Creates an Image (snapshot) from a Server by copying the contents of its disks. This creates a snapshot of the current state of the disk and copies it into an Image. If the Server is currently running you must make sure that its disk content is consistent. Otherwise, the created Image may not be readable.

To make sure disk content is consistent, we recommend to shut down the Server prior to creating an Image.

You can either create a `backup` Image that is bound to the Server and therefore will be deleted when the Server is deleted, or you can create an `snapshot` Image which is completely independent of the Server it was created from and will survive Server deletion. Backup Images are only available when the backup option is enabled for the Server. Snapshot Images are billed on a per GB basis.

    $cloud->servers->create_actions_create_image(
        id => 'test',
    );

=head2 create_actions_detach_from_network

Detaches a Server from a network. The interface for this network will vanish.

    $cloud->servers->create_actions_detach_from_network(
        id => 'test',
    );

=head2 create_actions_detach_iso

Detaches an ISO from a Server. In case no ISO Image is attached to the Server, the status of the returned Action is immediately set to `success`

    $cloud->servers->create_actions_detach_iso(
        id => 'test',
    );

=head2 create_actions_disable_backup

Disables the automatic backup option and deletes all existing Backups for a Server. No more additional charges for backups will be made.

Caution: This immediately removes all existing backups for the Server!

    $cloud->servers->create_actions_disable_backup(
        id => 'test',
    );

=head2 create_actions_disable_rescue

Disables the Hetzner Rescue System for a Server. This makes a Server start from its disks on next reboot.

Rescue Mode is automatically disabled when you first boot into it or if you do not use it for 60 minutes.

Disabling rescue mode will not reboot your Server — you will have to do this yourself.

    $cloud->servers->create_actions_disable_rescue(
        id => 'test',
    );

=head2 create_actions_enable_backup

Enables and configures the automatic daily backup option for the Server. Enabling automatic backups will increase the price of the Server by 20%. In return, you will get seven slots where Images of type backup can be stored.

Backups are automatically created daily.

    $cloud->servers->create_actions_enable_backup(
        id => 'test',
    );

=head2 create_actions_enable_rescue

Enable the Hetzner Rescue System for this Server. The next time a Server with enabled rescue mode boots it will start a special minimal Linux distribution designed for repair and reinstall.

In case a Server cannot boot on its own you can use this to access a Server’s disks.

Rescue Mode is automatically disabled when you first boot into it or if you do not use it for 60 minutes.

Enabling rescue mode will not [reboot](https://docs.hetzner.cloud/#server-actions-soft-reboot-a-server) your Server — you will have to do this yourself.

    $cloud->servers->create_actions_enable_rescue(
        id => 'test',
    );

=head2 create_actions_poweroff

Cuts power to the Server. This forcefully stops it without giving the Server operating system time to gracefully stop. May lead to data loss, equivalent to pulling the power cord. Power off should only be used when shutdown does not work.

    $cloud->servers->create_actions_poweroff(
        id => 'test',
    );

=head2 create_actions_poweron

Starts a Server by turning its power on.

    $cloud->servers->create_actions_poweron(
        id => 'test',
    );

=head2 create_actions_reboot

Reboots a Server gracefully by sending an ACPI request. The Server operating system must support ACPI and react to the request, otherwise the Server will not reboot.

    $cloud->servers->create_actions_reboot(
        id => 'test',
    );

=head2 create_actions_rebuild

Rebuilds a Server overwriting its disk with the content of an Image, thereby **destroying all data** on the target Server

The Image can either be one you have created earlier (`backup` or `snapshot` Image) or it can be a completely fresh `system` Image provided by us. You can get a list of all available Images with `GET /images`.

Your Server will automatically be powered off before the rebuild command executes.

    $cloud->servers->create_actions_rebuild(
        id => 'test',
    );

=head2 create_actions_remove_from_placement_group

Removes a Server from a Placement Group.

    $cloud->servers->create_actions_remove_from_placement_group(
        id => 'test',
    );

=head2 create_actions_request_console

Requests credentials for remote access via VNC over websocket to keyboard, monitor, and mouse for a Server. The provided URL is valid for 1 minute, after this period a new url needs to be created to connect to the Server. How long the connection is open after the initial connect is not subject to this timeout.

    $cloud->servers->create_actions_request_console(
        id => 'test',
    );

=head2 create_actions_reset

Cuts power to a Server and starts it again. This forcefully stops it without giving the Server operating system time to gracefully stop. This may lead to data loss, it’s equivalent to pulling the power cord and plugging it in again. Reset should only be used when reboot does not work.

    $cloud->servers->create_actions_reset(
        id => 'test',
    );

=head2 create_actions_reset_password

Resets the root password. Only works for Linux systems that are running the qemu guest agent. Server must be powered on (status `running`) in order for this operation to succeed.

This will generate a new password for this Server and return it.

If this does not succeed you can use the rescue system to netboot the Server and manually change your Server password by hand.

    $cloud->servers->create_actions_reset_password(
        id => 'test',
    );

=head2 create_actions_shutdown

Shuts down a Server gracefully by sending an ACPI shutdown request. The Server operating system must support ACPI
and react to the request, otherwise the Server will not shut down. Please note that the `action` status in this case
only reflects whether the action was sent to the server. It does not mean that the server actually shut down
successfully. If you need to ensure that the server is off, use the `poweroff` action

    $cloud->servers->create_actions_shutdown(
        id => 'test',
    );

=head2 get_actions

Returns a specific Action object for a Server.

    $cloud->servers->get_actions(
        action_id => 'test',
        id => 'test',
    );

=head2 list_metrics

Get Metrics for specified Server.

You must specify the type of metric to get: cpu, disk or network. You can also specify more than one type by comma separation, e.g. cpu,disk.

Depending on the type you will get different time series data

| Type    | Timeseries              | Unit      | Description                                          |
|---------|-------------------------|-----------|------------------------------------------------------|
| cpu     | cpu                     | percent   | Percent CPU usage                                    |
| disk    | disk.0.iops.read        | iop/s     | Number of read IO operations per second              |
|         | disk.0.iops.write       | iop/s     | Number of write IO operations per second             |
|         | disk.0.bandwidth.read   | bytes/s   | Bytes read per second                                |
|         | disk.0.bandwidth.write  | bytes/s   | Bytes written per second                             |
| network | network.0.pps.in        | packets/s | Public Network interface packets per second received |
|         | network.0.pps.out       | packets/s | Public Network interface packets per second sent     |
|         | network.0.bandwidth.in  | bytes/s   | Public Network interface bytes/s received            |
|         | network.0.bandwidth.out | bytes/s   | Public Network interface bytes/s sent                |

Metrics are available for the last 30 days only.

If you do not provide the step argument we will automatically adjust it so that a maximum of 200 samples are returned.

We limit the number of samples returned to a maximum of 500 and will adjust the step parameter accordingly.

    $cloud->servers->list_metrics(
        end => 'test',
        id => 'test',
        start => 'test',
        step => 'test',
        type => 'test',
    );

=head1 AUTHOR

Renee Baecker <reneeb@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is Copyright (c) 2018 by Renee Baecker.

This is free software, licensed under:

  The Artistic License 2.0 (GPL Compatible)

=cut
