From d4b1ab713355fb850985a82ebd9914af2de71520 Mon Sep 17 00:00:00 2001 From: stSolo Date: Thu, 22 Dec 2022 17:56:47 +0300 Subject: [PATCH] v1.0.0 --- CHANGELOG.md | 45 + Makefile | 5 + README.md | 438 ++++++- README_EN.md | 62 + client.go | 17 +- config/config.go | 40 +- interfaces/caller.go | 2 + pkg/cloudapi/account.go | 3 +- pkg/cloudapi/account/account.go | 3 + pkg/cloudapi/account/add_user.go | 24 +- pkg/cloudapi/account/audits.go | 18 +- pkg/cloudapi/account/create.go | 76 +- pkg/cloudapi/account/delete.go | 16 +- pkg/cloudapi/account/delete_user.go | 21 +- pkg/cloudapi/account/disable_enable.go | 11 +- pkg/cloudapi/account/get.go | 16 +- .../account/get_consumed_account_units.go | 20 +- .../get_consumed_cloud_units_by_type.go | 27 +- pkg/cloudapi/account/get_consumption.go | 28 +- .../account/get_reserved_account_units.go | 21 +- pkg/cloudapi/account/list.go | 16 +- pkg/cloudapi/account/list_computes.go | 17 +- pkg/cloudapi/account/list_deleted.go | 16 +- pkg/cloudapi/account/list_disks.go | 17 +- pkg/cloudapi/account/list_flipgroups.go | 19 +- pkg/cloudapi/account/list_rg.go | 17 +- pkg/cloudapi/account/list_templates.go | 24 +- pkg/cloudapi/account/list_vins.go | 17 +- pkg/cloudapi/account/models.go | 652 +++++++--- pkg/cloudapi/account/restore.go | 9 +- pkg/cloudapi/account/update.go | 69 +- pkg/cloudapi/account/update_user.go | 24 +- pkg/cloudapi/bservice.go | 8 + pkg/cloudapi/bservice/bservice.go | 3 + pkg/cloudapi/bservice/create.go | 33 +- pkg/cloudapi/bservice/delete.go | 24 +- pkg/cloudapi/bservice/disable.go | 19 +- pkg/cloudapi/bservice/enable.go | 20 +- pkg/cloudapi/bservice/get.go | 20 +- pkg/cloudapi/bservice/group_add.go | 86 +- pkg/cloudapi/bservice/group_compute_remove.go | 29 +- pkg/cloudapi/bservice/group_get.go | 28 +- pkg/cloudapi/bservice/group_parent_add.go | 30 +- pkg/cloudapi/bservice/group_parent_remove.go | 31 +- pkg/cloudapi/bservice/group_remove.go | 23 +- pkg/cloudapi/bservice/group_resize.go | 41 +- pkg/cloudapi/bservice/group_start.go | 23 +- pkg/cloudapi/bservice/group_stop.go | 28 +- pkg/cloudapi/bservice/group_update.go | 53 +- pkg/cloudapi/bservice/group_update_extnet.go | 30 +- pkg/cloudapi/bservice/group_update_vins.go | 30 +- pkg/cloudapi/bservice/list.go | 46 +- pkg/cloudapi/bservice/models.go | 415 +++++-- pkg/cloudapi/bservice/restore.go | 17 +- pkg/cloudapi/bservice/snapshot_create.go | 23 +- pkg/cloudapi/bservice/snapshot_delete.go | 23 +- pkg/cloudapi/bservice/snapshot_list.go | 22 +- pkg/cloudapi/bservice/snapshot_rollback.go | 23 +- pkg/cloudapi/bservice/start.go | 19 +- pkg/cloudapi/bservice/stop.go | 19 +- pkg/cloudapi/cloudapi.go | 9 +- pkg/cloudapi/compute.go | 3 +- .../compute/affinity_group_check_start.go | 13 +- pkg/cloudapi/compute/affinity_label_remove.go | 8 +- pkg/cloudapi/compute/affinity_label_set.go | 13 +- pkg/cloudapi/compute/affinity_relations.go | 19 +- pkg/cloudapi/compute/affinity_rule_add.go | 47 +- pkg/cloudapi/compute/affinity_rule_remove.go | 47 +- pkg/cloudapi/compute/affinity_rules_clear.go | 8 +- .../compute/anti_affinity_rule_add.go | 47 +- .../compute/anti_affinity_rule_remove.go | 47 +- .../compute/anti_affinity_rules_clear.go | 8 +- pkg/cloudapi/compute/attach_gpu.go | 14 +- pkg/cloudapi/compute/attach_pci_device.go | 18 +- pkg/cloudapi/compute/audits.go | 22 +- pkg/cloudapi/compute/cd_eject.go | 8 +- pkg/cloudapi/compute/cd_insert.go | 13 +- pkg/cloudapi/compute/clone.go | 24 +- pkg/cloudapi/compute/compute.go | 3 + pkg/cloudapi/compute/create_template.go | 28 +- pkg/cloudapi/compute/delete.go | 21 +- pkg/cloudapi/compute/detach_gpu.go | 14 +- pkg/cloudapi/compute/detach_pci_device.go | 18 +- pkg/cloudapi/compute/disable.go | 8 +- pkg/cloudapi/compute/disk_add.go | 50 +- pkg/cloudapi/compute/disk_attach.go | 14 +- pkg/cloudapi/compute/disk_del.go | 21 +- pkg/cloudapi/compute/disk_detach.go | 14 +- pkg/cloudapi/compute/disk_qos.go | 20 +- pkg/cloudapi/compute/disk_resize.go | 20 +- pkg/cloudapi/compute/enable.go | 8 +- pkg/cloudapi/compute/get.go | 17 +- pkg/cloudapi/compute/get_audits.go | 17 +- pkg/cloudapi/compute/get_console_url.go | 8 +- pkg/cloudapi/compute/get_log.go | 21 +- pkg/cloudapi/compute/list.go | 26 +- pkg/cloudapi/compute/list_deleted.go | 16 +- pkg/cloudapi/compute/list_pci_device.go | 14 +- pkg/cloudapi/compute/list_vgpu.go | 14 +- pkg/cloudapi/compute/models.go | 1092 ++++++++++++----- pkg/cloudapi/compute/move_to_rg.go | 32 +- pkg/cloudapi/compute/net_attach.go | 37 +- pkg/cloudapi/compute/net_detach.go | 19 +- pkg/cloudapi/compute/pause.go | 9 +- pkg/cloudapi/compute/pfw_add.go | 29 +- pkg/cloudapi/compute/pfw_del.go | 34 +- pkg/cloudapi/compute/pfw_list.go | 16 +- pkg/cloudapi/compute/pin_to_stack.go | 9 +- pkg/cloudapi/compute/power_cycle.go | 9 +- pkg/cloudapi/compute/reboot.go | 9 +- pkg/cloudapi/compute/redeploy.go | 33 +- pkg/cloudapi/compute/reset.go | 9 +- pkg/cloudapi/compute/resize.go | 26 +- pkg/cloudapi/compute/restore.go | 8 +- pkg/cloudapi/compute/resume.go | 9 +- pkg/cloudapi/compute/snapshot_create.go | 14 +- pkg/cloudapi/compute/snapshot_delete.go | 13 +- pkg/cloudapi/compute/snapshot_list.go | 16 +- pkg/cloudapi/compute/snapshot_rollback.go | 13 +- pkg/cloudapi/compute/snapshot_usage.go | 24 +- pkg/cloudapi/compute/start.go | 12 +- pkg/cloudapi/compute/stop.go | 14 +- pkg/cloudapi/compute/tag_add.go | 20 +- pkg/cloudapi/compute/tag_remove.go | 14 +- pkg/cloudapi/compute/unpin_from_stack.go | 9 +- pkg/cloudapi/compute/update.go | 19 +- pkg/cloudapi/compute/user_grant.go | 25 +- pkg/cloudapi/compute/user_list.go | 20 +- pkg/cloudapi/compute/user_revoke.go | 15 +- pkg/cloudapi/compute/user_update.go | 25 +- pkg/cloudapi/computeci.go | 3 +- pkg/cloudapi/computeci/computeci.go | 3 + pkg/cloudapi/computeci/get.go | 22 +- pkg/cloudapi/computeci/list.go | 29 +- pkg/cloudapi/computeci/models.go | 35 +- pkg/cloudapi/disks.go | 3 +- pkg/cloudapi/disks/create.go | 63 +- pkg/cloudapi/disks/delete.go | 28 +- pkg/cloudapi/disks/delete_disks.go | 24 +- pkg/cloudapi/disks/disks.go | 3 + pkg/cloudapi/disks/get.go | 18 +- pkg/cloudapi/disks/limitio.go | 83 +- pkg/cloudapi/disks/list.go | 42 +- pkg/cloudapi/disks/list_types.go | 11 +- pkg/cloudapi/disks/list_unattached.go | 15 +- pkg/cloudapi/disks/models.go | 358 ++++-- pkg/cloudapi/disks/rename.go | 15 +- pkg/cloudapi/disks/resize.go | 29 +- pkg/cloudapi/disks/restore.go | 13 +- pkg/cloudapi/disks/search.go | 22 +- pkg/cloudapi/disks/snapshot_delete.go | 14 +- pkg/cloudapi/disks/snapshot_rollback.go | 19 +- pkg/cloudapi/extnet.go | 3 +- pkg/cloudapi/extnet/extnet.go | 3 + pkg/cloudapi/extnet/get.go | 21 +- pkg/cloudapi/extnet/get_default.go | 2 +- pkg/cloudapi/extnet/list.go | 28 +- pkg/cloudapi/extnet/list_computes.go | 23 +- pkg/cloudapi/extnet/models.go | 235 +++- pkg/cloudapi/flipgroup.go | 3 +- pkg/cloudapi/flipgroup/compute_add.go | 23 +- pkg/cloudapi/flipgroup/compute_remove.go | 23 +- pkg/cloudapi/flipgroup/create.go | 58 +- pkg/cloudapi/flipgroup/delete.go | 18 +- pkg/cloudapi/flipgroup/edit.go | 26 +- pkg/cloudapi/flipgroup/flipgroup.go | 9 +- pkg/cloudapi/flipgroup/get.go | 25 +- pkg/cloudapi/flipgroup/list.go | 20 +- pkg/cloudapi/flipgroup/models.go | 129 +- pkg/cloudapi/image.go | 3 +- pkg/cloudapi/image/create.go | 94 +- pkg/cloudapi/image/create_virtual.go | 15 +- pkg/cloudapi/image/delete.go | 16 +- pkg/cloudapi/image/get.go | 22 +- pkg/cloudapi/image/image.go | 3 + pkg/cloudapi/image/link.go | 14 +- pkg/cloudapi/image/list.go | 25 +- pkg/cloudapi/image/models.go | 229 +++- pkg/cloudapi/image/rename.go | 15 +- pkg/cloudapi/k8ci.go | 3 +- pkg/cloudapi/k8ci/get.go | 20 +- pkg/cloudapi/k8ci/k8ci.go | 3 + pkg/cloudapi/k8ci/list.go | 29 +- pkg/cloudapi/k8ci/list_deleted.go | 20 +- pkg/cloudapi/k8ci/models.go | 27 +- pkg/cloudapi/k8s.go | 3 +- pkg/cloudapi/k8s/create.go | 103 +- pkg/cloudapi/k8s/delete.go | 17 +- pkg/cloudapi/k8s/delete_master_from_group.go | 22 +- pkg/cloudapi/k8s/delete_worker_from_group.go | 20 +- pkg/cloudapi/k8s/disable_enable.go | 13 +- pkg/cloudapi/k8s/find_group_by_label.go | 28 +- pkg/cloudapi/k8s/get.go | 16 +- pkg/cloudapi/k8s/get_config.go | 8 +- pkg/cloudapi/k8s/get_node_annotations.go | 13 +- pkg/cloudapi/k8s/get_node_taints.go | 13 +- pkg/cloudapi/k8s/k8s.go | 3 + pkg/cloudapi/k8s/list.go | 25 +- pkg/cloudapi/k8s/list_deleted.go | 20 +- pkg/cloudapi/k8s/models.go | 357 ++++-- pkg/cloudapi/k8s/restore.go | 9 +- pkg/cloudapi/k8s/start.go | 9 +- pkg/cloudapi/k8s/stop.go | 9 +- pkg/cloudapi/k8s/update.go | 21 +- pkg/cloudapi/k8s/worker_add.go | 21 +- pkg/cloudapi/k8s/worker_reset.go | 21 +- pkg/cloudapi/k8s/worker_restart.go | 21 +- pkg/cloudapi/k8s/workers_group_add.go | 70 +- pkg/cloudapi/k8s/workers_group_delete.go | 15 +- pkg/cloudapi/k8s/workers_group_get_by_name.go | 24 +- pkg/cloudapi/kvmppc.go | 3 +- pkg/cloudapi/kvmppc/create.go | 99 +- pkg/cloudapi/kvmppc/create_blank.go | 75 +- pkg/cloudapi/kvmppc/kvmppc.go | 3 + pkg/cloudapi/kvmx86.go | 3 +- pkg/cloudapi/kvmx86/create.go | 99 +- pkg/cloudapi/kvmx86/create_blank.go | 75 +- pkg/cloudapi/kvmx86/kvmx86.go | 3 + pkg/cloudapi/lb.go | 3 +- pkg/cloudapi/lb/backend_create.go | 71 +- pkg/cloudapi/lb/backend_delete.go | 15 +- pkg/cloudapi/lb/backend_server_add.go | 82 +- pkg/cloudapi/lb/backend_server_delete.go | 21 +- pkg/cloudapi/lb/backend_server_update.go | 82 +- pkg/cloudapi/lb/backend_update.go | 71 +- pkg/cloudapi/lb/config_reset.go | 9 +- pkg/cloudapi/lb/create.go | 41 +- pkg/cloudapi/lb/delete.go | 15 +- pkg/cloudapi/lb/disable_enable.go | 17 +- pkg/cloudapi/lb/frontend_bind.go | 37 +- pkg/cloudapi/lb/frontend_bind_delete.go | 24 +- pkg/cloudapi/lb/frontend_bind_update.go | 37 +- pkg/cloudapi/lb/frontend_create.go | 22 +- pkg/cloudapi/lb/frontend_delete.go | 15 +- pkg/cloudapi/lb/get.go | 20 +- pkg/cloudapi/lb/lb.go | 3 + pkg/cloudapi/lb/list.go | 28 +- pkg/cloudapi/lb/list_deleted.go | 23 +- pkg/cloudapi/lb/models.go | 269 +++- pkg/cloudapi/lb/restart.go | 8 +- pkg/cloudapi/lb/restore.go | 8 +- pkg/cloudapi/lb/update.go | 14 +- pkg/cloudapi/locations/get_url.go | 7 +- pkg/cloudapi/locations/list.go | 27 +- pkg/cloudapi/locations/locations.go | 3 + pkg/cloudapi/locations/models.go | 37 +- pkg/cloudapi/locatons.go | 3 +- pkg/cloudapi/rg.go | 3 +- pkg/cloudapi/rg/access_grant.go | 40 +- pkg/cloudapi/rg/access_revoke.go | 28 +- pkg/cloudapi/rg/affinity_group_computes.go | 28 +- pkg/cloudapi/rg/affinity_groups_get.go | 26 +- pkg/cloudapi/rg/affinity_groups_list.go | 20 +- pkg/cloudapi/rg/audits.go | 22 +- pkg/cloudapi/rg/create.go | 121 +- pkg/cloudapi/rg/delete.go | 35 +- pkg/cloudapi/rg/disable.go | 22 +- pkg/cloudapi/rg/enable.go | 22 +- pkg/cloudapi/rg/get.go | 27 +- pkg/cloudapi/rg/list.go | 29 +- pkg/cloudapi/rg/list_computes.go | 27 +- pkg/cloudapi/rg/list_deleted.go | 20 +- pkg/cloudapi/rg/list_lb.go | 22 +- pkg/cloudapi/rg/list_pfw.go | 22 +- pkg/cloudapi/rg/list_vins.go | 27 +- pkg/cloudapi/rg/models.go | 720 ++++++++--- pkg/cloudapi/rg/restore.go | 22 +- pkg/cloudapi/rg/rg.go | 3 + pkg/cloudapi/rg/set_def_net.go | 36 +- pkg/cloudapi/rg/update.go | 83 +- pkg/cloudapi/rg/usage.go | 26 +- pkg/cloudapi/sizes.go | 3 +- pkg/cloudapi/sizes/list.go | 32 +- pkg/cloudapi/sizes/models.go | 29 +- pkg/cloudapi/sizes/sizes.go | 4 + pkg/cloudapi/tasks.go | 3 +- pkg/cloudapi/tasks/get.go | 23 +- pkg/cloudapi/tasks/list.go | 26 +- pkg/cloudapi/tasks/models.go | 44 +- pkg/cloudapi/tasks/tasks.go | 3 + pkg/cloudapi/vins.go | 3 +- pkg/cloudapi/vins/audits.go | 18 +- pkg/cloudapi/vins/create_in_account.go | 36 +- pkg/cloudapi/vins/create_in_rg.go | 41 +- pkg/cloudapi/vins/delete.go | 24 +- pkg/cloudapi/vins/disable_enable.go | 11 +- pkg/cloudapi/vins/extnet_connect.go | 18 +- pkg/cloudapi/vins/extnet_disconnect.go | 8 +- pkg/cloudapi/vins/extnet_list.go | 22 +- pkg/cloudapi/vins/get.go | 16 +- pkg/cloudapi/vins/ip_list.go | 20 +- pkg/cloudapi/vins/ip_release.go | 18 +- pkg/cloudapi/vins/ip_reserve.go | 44 +- pkg/cloudapi/vins/list.go | 28 +- pkg/cloudapi/vins/list_deleted.go | 23 +- pkg/cloudapi/vins/models.go | 824 ++++++++++--- pkg/cloudapi/vins/nat_rule_add.go | 46 +- pkg/cloudapi/vins/nat_rule_del.go | 18 +- pkg/cloudapi/vins/nat_rule_list.go | 25 +- pkg/cloudapi/vins/restore.go | 9 +- pkg/cloudapi/vins/search.go | 31 +- pkg/cloudapi/vins/vins.go | 3 + pkg/cloudapi/vins/vnfdev_redeploy.go | 9 +- pkg/cloudapi/vins/vnfdev_restart.go | 9 +- pkg/cloudbroker/account.go | 1 + pkg/cloudbroker/account/account.go | 3 + pkg/cloudbroker/account/add_user.go | 28 +- pkg/cloudbroker/account/audits.go | 18 +- pkg/cloudbroker/account/create.go | 88 +- pkg/cloudbroker/account/delete.go | 21 +- pkg/cloudbroker/account/delete_accounts.go | 21 +- pkg/cloudbroker/account/delete_user.go | 21 +- pkg/cloudbroker/account/disable.go | 14 +- pkg/cloudbroker/account/disable_accounts.go | 11 +- pkg/cloudbroker/account/enable.go | 14 +- pkg/cloudbroker/account/enable_accounts.go | 11 +- pkg/cloudbroker/account/get.go | 24 +- pkg/cloudbroker/account/list.go | 25 +- pkg/cloudbroker/account/list_computes.go | 22 +- pkg/cloudbroker/account/list_deleted.go | 24 +- pkg/cloudbroker/account/list_disks.go | 22 +- pkg/cloudbroker/account/list_flip_groups.go | 26 +- pkg/cloudbroker/account/list_rg.go | 22 +- pkg/cloudbroker/account/list_vins.go | 20 +- pkg/cloudbroker/account/models.go | 606 ++++++--- pkg/cloudbroker/account/restore.go | 15 +- pkg/cloudbroker/account/update.go | 82 +- pkg/cloudbroker/account/update_user.go | 21 +- pkg/cloudbroker/cloudbroker.go | 3 + pkg/cloudbroker/compute.go | 3 +- .../compute/affinity_group_check_start.go | 46 + .../compute/affinity_label_remove.go | 45 + pkg/cloudbroker/compute/affinity_label_set.go | 51 + pkg/cloudbroker/compute/affinity_relations.go | 51 + pkg/cloudbroker/compute/affinity_rule_add.go | 103 ++ .../compute/affinity_rule_remove.go | 101 ++ .../compute/affinity_rules_clear.go | 45 + .../compute/anti_affinity_rule_add.go | 101 ++ .../compute/anti_affinity_rule_clear.go | 45 + .../compute/anti_affinity_rule_remove.go | 101 ++ pkg/cloudbroker/compute/attach_gpu.go | 52 + pkg/cloudbroker/compute/attach_pci_device.go | 52 + pkg/cloudbroker/compute/audits.go | 47 + pkg/cloudbroker/compute/boot_order_get.go | 47 + pkg/cloudbroker/compute/boot_order_set.go | 65 + pkg/cloudbroker/compute/cd_eject.go | 49 + pkg/cloudbroker/compute/cd_insert.go | 50 + pkg/cloudbroker/compute/clone.go | 64 + pkg/cloudbroker/compute/compute.go | 16 + pkg/cloudbroker/compute/computeci_set.go | 52 + pkg/cloudbroker/compute/computeci_unset.go | 45 + pkg/cloudbroker/compute/create_template.go | 86 ++ pkg/cloudbroker/compute/delete.go | 57 + pkg/cloudbroker/compute/detach_gpu.go | 50 + pkg/cloudbroker/compute/detach_pci_device.go | 52 + pkg/cloudbroker/compute/disable.go | 49 + pkg/cloudbroker/compute/disk_add.go | 84 ++ pkg/cloudbroker/compute/disk_attach.go | 56 + pkg/cloudbroker/compute/disk_del.go | 60 + pkg/cloudbroker/compute/disk_detach.go | 56 + pkg/cloudbroker/compute/disk_qos.go | 59 + pkg/cloudbroker/compute/disk_resize.go | 63 + pkg/cloudbroker/compute/enable.go | 49 + pkg/cloudbroker/compute/get.go | 51 + pkg/cloudbroker/compute/get_audits.go | 51 + pkg/cloudbroker/compute/get_console_url.go | 44 + pkg/cloudbroker/compute/get_log.go | 46 + pkg/cloudbroker/compute/list.go | 42 + pkg/cloudbroker/compute/list_deleted.go | 37 + pkg/cloudbroker/compute/list_gpu.go | 51 + pkg/cloudbroker/compute/list_pci_device.go | 47 + pkg/cloudbroker/compute/mass_delete.go | 53 + pkg/cloudbroker/compute/mass_reboot.go | 49 + .../compute/mass_repair_boot_fs.go | 49 + pkg/cloudbroker/compute/mass_start.go | 49 + pkg/cloudbroker/compute/mass_stop.go | 53 + pkg/cloudbroker/compute/migrate.go | 58 + pkg/cloudbroker/compute/migrate_storage.go | 70 ++ .../compute/migrate_storage_abort.go | 42 + .../compute/migrate_storage_clean_up.go | 44 + .../compute/migrate_storage_info.go | 42 + pkg/cloudbroker/compute/models.go | 778 ++++++++++++ pkg/cloudbroker/compute/move_to_rg.go | 67 + pkg/cloudbroker/compute/net_attach.go | 79 ++ pkg/cloudbroker/compute/net_detach.go | 57 + pkg/cloudbroker/compute/net_qos.go | 80 ++ pkg/cloudbroker/compute/pause.go | 49 + pkg/cloudbroker/compute/pfw_add.go | 83 ++ pkg/cloudbroker/compute/pfw_del.go | 72 ++ pkg/cloudbroker/compute/pfw_list.go | 51 + pkg/cloudbroker/compute/pin_to_stack.go | 56 + pkg/cloudbroker/compute/power_cycle.go | 45 + pkg/cloudbroker/compute/raise_down.go | 24 + pkg/cloudbroker/compute/reboot.go | 49 + pkg/cloudbroker/compute/redeploy.go | 73 ++ pkg/cloudbroker/compute/registration.go | 52 + pkg/cloudbroker/compute/repair_boot_fs.go | 49 + pkg/cloudbroker/compute/reset.go | 49 + pkg/cloudbroker/compute/resize.go | 63 + pkg/cloudbroker/compute/restore.go | 49 + pkg/cloudbroker/compute/resume.go | 49 + pkg/cloudbroker/compute/snapshot_create.go | 50 + pkg/cloudbroker/compute/snapshot_delete.go | 52 + .../compute/snapshot_evict_disk.go | 52 + pkg/cloudbroker/compute/snapshot_list.go | 47 + pkg/cloudbroker/compute/snapshot_rollback.go | 52 + pkg/cloudbroker/compute/snapshot_usage.go | 54 + pkg/cloudbroker/compute/start.go | 57 + pkg/cloudbroker/compute/stop.go | 53 + pkg/cloudbroker/compute/tag_add.go | 59 + pkg/cloudbroker/compute/tag_remove.go | 52 + pkg/cloudbroker/compute/unpin_from_stack.go | 45 + pkg/cloudbroker/compute/update.go | 57 + pkg/cloudbroker/compute/user_grant.go | 69 ++ pkg/cloudbroker/compute/user_list.go | 47 + pkg/cloudbroker/compute/user_revoke.go | 52 + pkg/cloudbroker/compute/user_update.go | 69 ++ pkg/cloudbroker/computeci.go | 9 - pkg/cloudbroker/disks.go | 1 + pkg/cloudbroker/disks/create.go | 64 +- pkg/cloudbroker/disks/delete.go | 27 +- pkg/cloudbroker/disks/delete_disks.go | 22 +- pkg/cloudbroker/disks/disks.go | 3 + pkg/cloudbroker/disks/get.go | 17 +- pkg/cloudbroker/disks/limit_io.go | 82 +- pkg/cloudbroker/disks/list.go | 25 +- pkg/cloudbroker/disks/list_deleted.go | 32 +- pkg/cloudbroker/disks/list_types.go | 10 +- pkg/cloudbroker/disks/list_unattached.go | 28 +- pkg/cloudbroker/disks/models.go | 316 +++-- pkg/cloudbroker/disks/rename.go | 15 +- pkg/cloudbroker/disks/resize.go | 24 +- pkg/cloudbroker/disks/restore.go | 12 +- pkg/cloudbroker/disks/search.go | 30 +- pkg/cloudbroker/disks/snapshot_delete.go | 14 +- pkg/cloudbroker/disks/snapshot_rollback.go | 19 +- pkg/cloudbroker/extnet.go | 3 +- pkg/cloudbroker/extnet/access_add.go | 54 + pkg/cloudbroker/extnet/access_remove.go | 54 + pkg/cloudbroker/extnet/create.go | 114 ++ pkg/cloudbroker/extnet/default_qos_update.go | 57 + pkg/cloudbroker/extnet/destroy.go | 45 + pkg/cloudbroker/extnet/device_deploy.go | 45 + pkg/cloudbroker/extnet/device_migrate.go | 45 + pkg/cloudbroker/extnet/device_remove.go | 45 + pkg/cloudbroker/extnet/device_restart.go | 45 + pkg/cloudbroker/extnet/disable.go | 45 + pkg/cloudbroker/extnet/dns_apply.go | 49 + pkg/cloudbroker/extnet/enable.go | 45 + pkg/cloudbroker/extnet/extnet.go | 16 + pkg/cloudbroker/extnet/get.go | 47 + pkg/cloudbroker/extnet/get_default.go | 24 + pkg/cloudbroker/extnet/ips_exclude.go | 52 + pkg/cloudbroker/extnet/ips_exclude_range.go | 59 + pkg/cloudbroker/extnet/ips_include.go | 52 + pkg/cloudbroker/extnet/ips_include_range.go | 59 + pkg/cloudbroker/extnet/list.go | 41 + pkg/cloudbroker/extnet/models.go | 147 +++ pkg/cloudbroker/extnet/ntp_apply.go | 49 + pkg/cloudbroker/extnet/raise_down.go | 24 + pkg/cloudbroker/extnet/set_default.go | 45 + pkg/cloudbroker/extnet/update.go | 53 + pkg/cloudbroker/flipgroup.go | 9 - pkg/cloudbroker/grid.go | 8 + pkg/cloudbroker/grid/add.go | 59 + pkg/cloudbroker/grid/change_settings.go | 52 + pkg/cloudbroker/grid/check_vms.go | 45 + pkg/cloudbroker/grid/create_system_space.go | 79 ++ .../grid/execute_maintenance_script.go | 59 + pkg/cloudbroker/grid/get.go | 47 + pkg/cloudbroker/grid/get_backup.go | 56 + pkg/cloudbroker/grid/get_diagnosis.go | 56 + pkg/cloudbroker/grid/grid.go | 18 + pkg/cloudbroker/grid/list.go | 37 + pkg/cloudbroker/grid/list_emails.go | 26 + pkg/cloudbroker/grid/models.go | 58 + pkg/cloudbroker/grid/purge_logs.go | 53 + pkg/cloudbroker/grid/rename.go | 52 + pkg/cloudbroker/grid/services_restart.go | 52 + .../grid/set_cpu_allocation_ratio.go | 52 + .../grid/set_mem_allocation_ratio.go | 52 + pkg/cloudbroker/grid/status.go | 41 + pkg/cloudbroker/image.go | 1 + pkg/cloudbroker/image/computeci_set.go | 13 +- pkg/cloudbroker/image/computeci_unset.go | 8 +- pkg/cloudbroker/image/create_cdrom_image.go | 64 +- pkg/cloudbroker/image/create_image.go | 100 +- pkg/cloudbroker/image/create_virtual.go | 13 +- pkg/cloudbroker/image/delete.go | 20 +- pkg/cloudbroker/image/delete_cdrom_image.go | 15 +- pkg/cloudbroker/image/delete_images.go | 23 +- pkg/cloudbroker/image/disable.go | 8 +- pkg/cloudbroker/image/edit.go | 38 +- pkg/cloudbroker/image/enable.go | 10 +- pkg/cloudbroker/image/get.go | 16 +- pkg/cloudbroker/image/image.go | 3 + pkg/cloudbroker/image/link.go | 15 +- pkg/cloudbroker/image/list.go | 19 +- pkg/cloudbroker/image/list_stacks.go | 18 +- pkg/cloudbroker/image/models.go | 280 ++++- pkg/cloudbroker/image/rename.go | 15 +- pkg/cloudbroker/image/share.go | 13 +- pkg/cloudbroker/image/sync_create_image.go | 104 +- pkg/cloudbroker/image/update_nodes.go | 13 +- pkg/cloudbroker/k8ci.go | 3 +- pkg/cloudbroker/k8ci/create.go | 128 ++ pkg/cloudbroker/k8ci/delete.go | 49 + pkg/cloudbroker/k8ci/disable.go | 45 + pkg/cloudbroker/k8ci/enable.go | 45 + pkg/cloudbroker/k8ci/get.go | 47 + pkg/cloudbroker/k8ci/k8ci.go | 18 + pkg/cloudbroker/k8ci/list.go | 41 + pkg/cloudbroker/k8ci/list_deleted.go | 37 + pkg/cloudbroker/k8ci/models.go | 63 + pkg/cloudbroker/k8ci/restore.go | 45 + pkg/cloudbroker/k8s.go | 3 +- pkg/cloudbroker/k8s/create.go | 141 +++ pkg/cloudbroker/k8s/delete.go | 50 + .../k8s/delete_master_from_group.go | 59 + .../k8s/delete_worker_from_group.go | 59 + pkg/cloudbroker/k8s/disable.go | 45 + pkg/cloudbroker/k8s/enable.go | 45 + pkg/cloudbroker/k8s/find_group_by_label.go | 59 + pkg/cloudbroker/k8s/get.go | 47 + pkg/cloudbroker/k8s/get_config.go | 42 + pkg/cloudbroker/k8s/get_node_annotations.go | 49 + pkg/cloudbroker/k8s/get_node_labels.go | 49 + pkg/cloudbroker/k8s/get_node_taints.go | 49 + pkg/cloudbroker/k8s/k8s.go | 18 + pkg/cloudbroker/k8s/list.go | 42 + pkg/cloudbroker/k8s/list_deleted.go | 38 + pkg/cloudbroker/k8s/models.go | 292 +++++ pkg/cloudbroker/k8s/restore.go | 45 + pkg/cloudbroker/k8s/start.go | 45 + pkg/cloudbroker/k8s/stop.go | 45 + pkg/cloudbroker/k8s/update.go | 55 + pkg/cloudbroker/k8s/worker_add.go | 58 + pkg/cloudbroker/k8s/worker_reset.go | 59 + pkg/cloudbroker/k8s/worker_restart.go | 58 + pkg/cloudbroker/k8s/workers_group_add.go | 90 ++ pkg/cloudbroker/k8s/workers_group_delete.go | 52 + .../k8s/workers_group_get_by_name.go | 54 + pkg/cloudbroker/kvmppc.go | 1 + pkg/cloudbroker/kvmppc/create.go | 103 +- pkg/cloudbroker/kvmppc/create_blank.go | 69 +- pkg/cloudbroker/kvmppc/kvmppc.go | 3 + pkg/cloudbroker/kvmppc/mass_create.go | 90 +- pkg/cloudbroker/kvmx86.go | 1 + pkg/cloudbroker/kvmx86/create.go | 105 +- pkg/cloudbroker/kvmx86/create_blank.go | 71 +- pkg/cloudbroker/kvmx86/kvmx86.go | 3 + pkg/cloudbroker/kvmx86/mass_create.go | 92 +- pkg/cloudbroker/lb.go | 3 +- pkg/cloudbroker/lb/backend_create.go | 106 ++ pkg/cloudbroker/lb/backend_delete.go | 53 + pkg/cloudbroker/lb/backend_server_add.go | 114 ++ pkg/cloudbroker/lb/backend_server_delete.go | 62 + pkg/cloudbroker/lb/backend_server_update.go | 114 ++ pkg/cloudbroker/lb/backend_update.go | 100 ++ pkg/cloudbroker/lb/config_reset.go | 46 + pkg/cloudbroker/lb/create.go | 79 ++ pkg/cloudbroker/lb/delete.go | 49 + pkg/cloudbroker/lb/disable.go | 45 + pkg/cloudbroker/lb/enable.go | 45 + pkg/cloudbroker/lb/frontend_bind.go | 76 ++ pkg/cloudbroker/lb/frontend_bind_delete.go | 59 + pkg/cloudbroker/lb/frontend_binding_update.go | 76 ++ pkg/cloudbroker/lb/frontend_create.go | 61 + pkg/cloudbroker/lb/frontend_delete.go | 53 + pkg/cloudbroker/lb/get.go | 47 + pkg/cloudbroker/lb/lb.go | 16 + pkg/cloudbroker/lb/list.go | 42 + pkg/cloudbroker/lb/list_deleted.go | 38 + pkg/cloudbroker/lb/models.go | 227 ++++ pkg/cloudbroker/lb/restart.go | 45 + pkg/cloudbroker/lb/restore.go | 45 + pkg/cloudbroker/lb/start.go | 45 + pkg/cloudbroker/lb/stop.go | 45 + pkg/cloudbroker/lb/update.go | 53 + pkg/cloudbroker/locatons.go | 7 - pkg/cloudbroker/rg.go | 1 + pkg/cloudbroker/rg/access_grant.go | 32 +- pkg/cloudbroker/rg/access_revoke.go | 20 +- pkg/cloudbroker/rg/affinity_group_computes.go | 25 +- pkg/cloudbroker/rg/affinity_groups_get.go | 23 +- pkg/cloudbroker/rg/affinity_groups_list.go | 17 +- pkg/cloudbroker/rg/audits.go | 20 +- pkg/cloudbroker/rg/create.go | 116 +- pkg/cloudbroker/rg/delete.go | 28 +- pkg/cloudbroker/rg/disable.go | 15 +- pkg/cloudbroker/rg/enable.go | 17 +- pkg/cloudbroker/rg/get.go | 21 +- pkg/cloudbroker/rg/list.go | 20 +- pkg/cloudbroker/rg/list_computes.go | 19 +- pkg/cloudbroker/rg/list_deleted.go | 15 +- pkg/cloudbroker/rg/list_lb.go | 16 +- pkg/cloudbroker/rg/list_pfw.go | 16 +- pkg/cloudbroker/rg/list_vins.go | 19 +- pkg/cloudbroker/rg/mass_delete.go | 28 +- pkg/cloudbroker/rg/mass_disable.go | 15 +- pkg/cloudbroker/rg/mass_enable.go | 15 +- pkg/cloudbroker/rg/models.go | 744 ++++++++--- pkg/cloudbroker/rg/restore.go | 15 +- pkg/cloudbroker/rg/rg.go | 7 +- pkg/cloudbroker/rg/set_def_net.go | 30 +- pkg/cloudbroker/rg/update.go | 79 +- pkg/cloudbroker/rg/usage.go | 21 +- pkg/cloudbroker/sep.go | 8 + pkg/cloudbroker/sep/access_grant.go | 53 + pkg/cloudbroker/sep/access_grant_to_pool.go | 60 + pkg/cloudbroker/sep/access_revoke.go | 52 + pkg/cloudbroker/sep/access_revoke_to_pool.go | 60 + pkg/cloudbroker/sep/add_consumer_nodes.go | 52 + pkg/cloudbroker/sep/add_provider_nodes.go | 52 + pkg/cloudbroker/sep/config_field_edit.go | 78 ++ pkg/cloudbroker/sep/config_insert.go | 52 + pkg/cloudbroker/sep/config_validate.go | 52 + pkg/cloudbroker/sep/consumption.go | 47 + pkg/cloudbroker/sep/create.go | 79 ++ pkg/cloudbroker/sep/decommission.go | 49 + pkg/cloudbroker/sep/del_consumer_nodes.go | 52 + pkg/cloudbroker/sep/delete.go | 45 + pkg/cloudbroker/sep/disable.go | 45 + pkg/cloudbroker/sep/disk_list.go | 51 + pkg/cloudbroker/sep/enable.go | 45 + pkg/cloudbroker/sep/get.go | 47 + pkg/cloudbroker/sep/get_config.go | 47 + pkg/cloudbroker/sep/get_pool.go | 54 + pkg/cloudbroker/sep/list.go | 37 + pkg/cloudbroker/sep/models.go | 127 ++ pkg/cloudbroker/sep/sep.go | 18 + pkg/cloudbroker/sep/update_capacity_limit.go | 45 + pkg/cloudbroker/sizes.go | 9 - pkg/cloudbroker/tasks.go | 3 +- pkg/cloudbroker/tasks/get.go | 47 + pkg/cloudbroker/tasks/list.go | 37 + pkg/cloudbroker/tasks/models.go | 71 ++ pkg/cloudbroker/tasks/tasks.go | 16 + pkg/cloudbroker/vins.go | 3 +- pkg/cloudbroker/vins/audits.go | 47 + pkg/cloudbroker/vins/create_in_account.go | 72 ++ pkg/cloudbroker/vins/create_in_rg.go | 76 ++ pkg/cloudbroker/vins/default_qos_update.go | 57 + pkg/cloudbroker/vins/delete.go | 61 + pkg/cloudbroker/vins/disable.go | 49 + pkg/cloudbroker/vins/enable.go | 49 + pkg/cloudbroker/vins/extnet_connect.go | 60 + pkg/cloudbroker/vins/extnet_disconnect.go | 49 + pkg/cloudbroker/vins/extnet_list.go | 51 + pkg/cloudbroker/vins/get.go | 51 + pkg/cloudbroker/vins/ip_list.go | 47 + pkg/cloudbroker/vins/ip_release.go | 54 + pkg/cloudbroker/vins/ip_reserve.go | 79 ++ pkg/cloudbroker/vins/list.go | 37 + pkg/cloudbroker/vins/list_deleted.go | 37 + pkg/cloudbroker/vins/mass_delete.go | 56 + pkg/cloudbroker/vins/mass_disable.go | 43 + pkg/cloudbroker/vins/mass_enable.go | 43 + pkg/cloudbroker/vins/models.go | 673 ++++++++++ pkg/cloudbroker/vins/nat_rule_add.go | 81 ++ pkg/cloudbroker/vins/nat_rule_del.go | 57 + pkg/cloudbroker/vins/nat_rule_list.go | 51 + pkg/cloudbroker/vins/net_qos.go | 57 + pkg/cloudbroker/vins/raise_down.go | 24 + pkg/cloudbroker/vins/restore.go | 49 + pkg/cloudbroker/vins/search.go | 49 + pkg/cloudbroker/vins/vins.go | 18 + pkg/cloudbroker/vins/vnfdev_redeploy.go | 49 + pkg/cloudbroker/vins/vnfdev_reset.go | 49 + pkg/cloudbroker/vins/vnfdev_restart.go | 49 + pkg/cloudbroker/vins/vnfdev_start.go | 49 + pkg/cloudbroker/vins/vnfdev_stop.go | 49 + 672 files changed, 28399 insertions(+), 4309 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 Makefile create mode 100644 README_EN.md create mode 100644 pkg/cloudapi/bservice.go create mode 100644 pkg/cloudbroker/compute/affinity_group_check_start.go create mode 100644 pkg/cloudbroker/compute/affinity_label_remove.go create mode 100644 pkg/cloudbroker/compute/affinity_label_set.go create mode 100644 pkg/cloudbroker/compute/affinity_relations.go create mode 100644 pkg/cloudbroker/compute/affinity_rule_add.go create mode 100644 pkg/cloudbroker/compute/affinity_rule_remove.go create mode 100644 pkg/cloudbroker/compute/affinity_rules_clear.go create mode 100644 pkg/cloudbroker/compute/anti_affinity_rule_add.go create mode 100644 pkg/cloudbroker/compute/anti_affinity_rule_clear.go create mode 100644 pkg/cloudbroker/compute/anti_affinity_rule_remove.go create mode 100644 pkg/cloudbroker/compute/attach_gpu.go create mode 100644 pkg/cloudbroker/compute/attach_pci_device.go create mode 100644 pkg/cloudbroker/compute/audits.go create mode 100644 pkg/cloudbroker/compute/boot_order_get.go create mode 100644 pkg/cloudbroker/compute/boot_order_set.go create mode 100644 pkg/cloudbroker/compute/cd_eject.go create mode 100644 pkg/cloudbroker/compute/cd_insert.go create mode 100644 pkg/cloudbroker/compute/clone.go create mode 100644 pkg/cloudbroker/compute/compute.go create mode 100644 pkg/cloudbroker/compute/computeci_set.go create mode 100644 pkg/cloudbroker/compute/computeci_unset.go create mode 100644 pkg/cloudbroker/compute/create_template.go create mode 100644 pkg/cloudbroker/compute/delete.go create mode 100644 pkg/cloudbroker/compute/detach_gpu.go create mode 100644 pkg/cloudbroker/compute/detach_pci_device.go create mode 100644 pkg/cloudbroker/compute/disable.go create mode 100644 pkg/cloudbroker/compute/disk_add.go create mode 100644 pkg/cloudbroker/compute/disk_attach.go create mode 100644 pkg/cloudbroker/compute/disk_del.go create mode 100644 pkg/cloudbroker/compute/disk_detach.go create mode 100644 pkg/cloudbroker/compute/disk_qos.go create mode 100644 pkg/cloudbroker/compute/disk_resize.go create mode 100644 pkg/cloudbroker/compute/enable.go create mode 100644 pkg/cloudbroker/compute/get.go create mode 100644 pkg/cloudbroker/compute/get_audits.go create mode 100644 pkg/cloudbroker/compute/get_console_url.go create mode 100644 pkg/cloudbroker/compute/get_log.go create mode 100644 pkg/cloudbroker/compute/list.go create mode 100644 pkg/cloudbroker/compute/list_deleted.go create mode 100644 pkg/cloudbroker/compute/list_gpu.go create mode 100644 pkg/cloudbroker/compute/list_pci_device.go create mode 100644 pkg/cloudbroker/compute/mass_delete.go create mode 100644 pkg/cloudbroker/compute/mass_reboot.go create mode 100644 pkg/cloudbroker/compute/mass_repair_boot_fs.go create mode 100644 pkg/cloudbroker/compute/mass_start.go create mode 100644 pkg/cloudbroker/compute/mass_stop.go create mode 100644 pkg/cloudbroker/compute/migrate.go create mode 100644 pkg/cloudbroker/compute/migrate_storage.go create mode 100644 pkg/cloudbroker/compute/migrate_storage_abort.go create mode 100644 pkg/cloudbroker/compute/migrate_storage_clean_up.go create mode 100644 pkg/cloudbroker/compute/migrate_storage_info.go create mode 100644 pkg/cloudbroker/compute/models.go create mode 100644 pkg/cloudbroker/compute/move_to_rg.go create mode 100644 pkg/cloudbroker/compute/net_attach.go create mode 100644 pkg/cloudbroker/compute/net_detach.go create mode 100644 pkg/cloudbroker/compute/net_qos.go create mode 100644 pkg/cloudbroker/compute/pause.go create mode 100644 pkg/cloudbroker/compute/pfw_add.go create mode 100644 pkg/cloudbroker/compute/pfw_del.go create mode 100644 pkg/cloudbroker/compute/pfw_list.go create mode 100644 pkg/cloudbroker/compute/pin_to_stack.go create mode 100644 pkg/cloudbroker/compute/power_cycle.go create mode 100644 pkg/cloudbroker/compute/raise_down.go create mode 100644 pkg/cloudbroker/compute/reboot.go create mode 100644 pkg/cloudbroker/compute/redeploy.go create mode 100644 pkg/cloudbroker/compute/registration.go create mode 100644 pkg/cloudbroker/compute/repair_boot_fs.go create mode 100644 pkg/cloudbroker/compute/reset.go create mode 100644 pkg/cloudbroker/compute/resize.go create mode 100644 pkg/cloudbroker/compute/restore.go create mode 100644 pkg/cloudbroker/compute/resume.go create mode 100644 pkg/cloudbroker/compute/snapshot_create.go create mode 100644 pkg/cloudbroker/compute/snapshot_delete.go create mode 100644 pkg/cloudbroker/compute/snapshot_evict_disk.go create mode 100644 pkg/cloudbroker/compute/snapshot_list.go create mode 100644 pkg/cloudbroker/compute/snapshot_rollback.go create mode 100644 pkg/cloudbroker/compute/snapshot_usage.go create mode 100644 pkg/cloudbroker/compute/start.go create mode 100644 pkg/cloudbroker/compute/stop.go create mode 100644 pkg/cloudbroker/compute/tag_add.go create mode 100644 pkg/cloudbroker/compute/tag_remove.go create mode 100644 pkg/cloudbroker/compute/unpin_from_stack.go create mode 100644 pkg/cloudbroker/compute/update.go create mode 100644 pkg/cloudbroker/compute/user_grant.go create mode 100644 pkg/cloudbroker/compute/user_list.go create mode 100644 pkg/cloudbroker/compute/user_revoke.go create mode 100644 pkg/cloudbroker/compute/user_update.go delete mode 100644 pkg/cloudbroker/computeci.go create mode 100644 pkg/cloudbroker/extnet/access_add.go create mode 100644 pkg/cloudbroker/extnet/access_remove.go create mode 100644 pkg/cloudbroker/extnet/create.go create mode 100644 pkg/cloudbroker/extnet/default_qos_update.go create mode 100644 pkg/cloudbroker/extnet/destroy.go create mode 100644 pkg/cloudbroker/extnet/device_deploy.go create mode 100644 pkg/cloudbroker/extnet/device_migrate.go create mode 100644 pkg/cloudbroker/extnet/device_remove.go create mode 100644 pkg/cloudbroker/extnet/device_restart.go create mode 100644 pkg/cloudbroker/extnet/disable.go create mode 100644 pkg/cloudbroker/extnet/dns_apply.go create mode 100644 pkg/cloudbroker/extnet/enable.go create mode 100644 pkg/cloudbroker/extnet/extnet.go create mode 100644 pkg/cloudbroker/extnet/get.go create mode 100644 pkg/cloudbroker/extnet/get_default.go create mode 100644 pkg/cloudbroker/extnet/ips_exclude.go create mode 100644 pkg/cloudbroker/extnet/ips_exclude_range.go create mode 100644 pkg/cloudbroker/extnet/ips_include.go create mode 100644 pkg/cloudbroker/extnet/ips_include_range.go create mode 100644 pkg/cloudbroker/extnet/list.go create mode 100644 pkg/cloudbroker/extnet/models.go create mode 100644 pkg/cloudbroker/extnet/ntp_apply.go create mode 100644 pkg/cloudbroker/extnet/raise_down.go create mode 100644 pkg/cloudbroker/extnet/set_default.go create mode 100644 pkg/cloudbroker/extnet/update.go delete mode 100644 pkg/cloudbroker/flipgroup.go create mode 100644 pkg/cloudbroker/grid.go create mode 100644 pkg/cloudbroker/grid/add.go create mode 100644 pkg/cloudbroker/grid/change_settings.go create mode 100644 pkg/cloudbroker/grid/check_vms.go create mode 100644 pkg/cloudbroker/grid/create_system_space.go create mode 100644 pkg/cloudbroker/grid/execute_maintenance_script.go create mode 100644 pkg/cloudbroker/grid/get.go create mode 100644 pkg/cloudbroker/grid/get_backup.go create mode 100644 pkg/cloudbroker/grid/get_diagnosis.go create mode 100644 pkg/cloudbroker/grid/grid.go create mode 100644 pkg/cloudbroker/grid/list.go create mode 100644 pkg/cloudbroker/grid/list_emails.go create mode 100644 pkg/cloudbroker/grid/models.go create mode 100644 pkg/cloudbroker/grid/purge_logs.go create mode 100644 pkg/cloudbroker/grid/rename.go create mode 100644 pkg/cloudbroker/grid/services_restart.go create mode 100644 pkg/cloudbroker/grid/set_cpu_allocation_ratio.go create mode 100644 pkg/cloudbroker/grid/set_mem_allocation_ratio.go create mode 100644 pkg/cloudbroker/grid/status.go create mode 100644 pkg/cloudbroker/k8ci/create.go create mode 100644 pkg/cloudbroker/k8ci/delete.go create mode 100644 pkg/cloudbroker/k8ci/disable.go create mode 100644 pkg/cloudbroker/k8ci/enable.go create mode 100644 pkg/cloudbroker/k8ci/get.go create mode 100644 pkg/cloudbroker/k8ci/k8ci.go create mode 100644 pkg/cloudbroker/k8ci/list.go create mode 100644 pkg/cloudbroker/k8ci/list_deleted.go create mode 100644 pkg/cloudbroker/k8ci/models.go create mode 100644 pkg/cloudbroker/k8ci/restore.go create mode 100644 pkg/cloudbroker/k8s/create.go create mode 100644 pkg/cloudbroker/k8s/delete.go create mode 100644 pkg/cloudbroker/k8s/delete_master_from_group.go create mode 100644 pkg/cloudbroker/k8s/delete_worker_from_group.go create mode 100644 pkg/cloudbroker/k8s/disable.go create mode 100644 pkg/cloudbroker/k8s/enable.go create mode 100644 pkg/cloudbroker/k8s/find_group_by_label.go create mode 100644 pkg/cloudbroker/k8s/get.go create mode 100644 pkg/cloudbroker/k8s/get_config.go create mode 100644 pkg/cloudbroker/k8s/get_node_annotations.go create mode 100644 pkg/cloudbroker/k8s/get_node_labels.go create mode 100644 pkg/cloudbroker/k8s/get_node_taints.go create mode 100644 pkg/cloudbroker/k8s/k8s.go create mode 100644 pkg/cloudbroker/k8s/list.go create mode 100644 pkg/cloudbroker/k8s/list_deleted.go create mode 100644 pkg/cloudbroker/k8s/models.go create mode 100644 pkg/cloudbroker/k8s/restore.go create mode 100644 pkg/cloudbroker/k8s/start.go create mode 100644 pkg/cloudbroker/k8s/stop.go create mode 100644 pkg/cloudbroker/k8s/update.go create mode 100644 pkg/cloudbroker/k8s/worker_add.go create mode 100644 pkg/cloudbroker/k8s/worker_reset.go create mode 100644 pkg/cloudbroker/k8s/worker_restart.go create mode 100644 pkg/cloudbroker/k8s/workers_group_add.go create mode 100644 pkg/cloudbroker/k8s/workers_group_delete.go create mode 100644 pkg/cloudbroker/k8s/workers_group_get_by_name.go create mode 100644 pkg/cloudbroker/lb/backend_create.go create mode 100644 pkg/cloudbroker/lb/backend_delete.go create mode 100644 pkg/cloudbroker/lb/backend_server_add.go create mode 100644 pkg/cloudbroker/lb/backend_server_delete.go create mode 100644 pkg/cloudbroker/lb/backend_server_update.go create mode 100644 pkg/cloudbroker/lb/backend_update.go create mode 100644 pkg/cloudbroker/lb/config_reset.go create mode 100644 pkg/cloudbroker/lb/create.go create mode 100644 pkg/cloudbroker/lb/delete.go create mode 100644 pkg/cloudbroker/lb/disable.go create mode 100644 pkg/cloudbroker/lb/enable.go create mode 100644 pkg/cloudbroker/lb/frontend_bind.go create mode 100644 pkg/cloudbroker/lb/frontend_bind_delete.go create mode 100644 pkg/cloudbroker/lb/frontend_binding_update.go create mode 100644 pkg/cloudbroker/lb/frontend_create.go create mode 100644 pkg/cloudbroker/lb/frontend_delete.go create mode 100644 pkg/cloudbroker/lb/get.go create mode 100644 pkg/cloudbroker/lb/lb.go create mode 100644 pkg/cloudbroker/lb/list.go create mode 100644 pkg/cloudbroker/lb/list_deleted.go create mode 100644 pkg/cloudbroker/lb/models.go create mode 100644 pkg/cloudbroker/lb/restart.go create mode 100644 pkg/cloudbroker/lb/restore.go create mode 100644 pkg/cloudbroker/lb/start.go create mode 100644 pkg/cloudbroker/lb/stop.go create mode 100644 pkg/cloudbroker/lb/update.go delete mode 100644 pkg/cloudbroker/locatons.go create mode 100644 pkg/cloudbroker/sep.go create mode 100644 pkg/cloudbroker/sep/access_grant.go create mode 100644 pkg/cloudbroker/sep/access_grant_to_pool.go create mode 100644 pkg/cloudbroker/sep/access_revoke.go create mode 100644 pkg/cloudbroker/sep/access_revoke_to_pool.go create mode 100644 pkg/cloudbroker/sep/add_consumer_nodes.go create mode 100644 pkg/cloudbroker/sep/add_provider_nodes.go create mode 100644 pkg/cloudbroker/sep/config_field_edit.go create mode 100644 pkg/cloudbroker/sep/config_insert.go create mode 100644 pkg/cloudbroker/sep/config_validate.go create mode 100644 pkg/cloudbroker/sep/consumption.go create mode 100644 pkg/cloudbroker/sep/create.go create mode 100644 pkg/cloudbroker/sep/decommission.go create mode 100644 pkg/cloudbroker/sep/del_consumer_nodes.go create mode 100644 pkg/cloudbroker/sep/delete.go create mode 100644 pkg/cloudbroker/sep/disable.go create mode 100644 pkg/cloudbroker/sep/disk_list.go create mode 100644 pkg/cloudbroker/sep/enable.go create mode 100644 pkg/cloudbroker/sep/get.go create mode 100644 pkg/cloudbroker/sep/get_config.go create mode 100644 pkg/cloudbroker/sep/get_pool.go create mode 100644 pkg/cloudbroker/sep/list.go create mode 100644 pkg/cloudbroker/sep/models.go create mode 100644 pkg/cloudbroker/sep/sep.go create mode 100644 pkg/cloudbroker/sep/update_capacity_limit.go delete mode 100644 pkg/cloudbroker/sizes.go create mode 100644 pkg/cloudbroker/tasks/get.go create mode 100644 pkg/cloudbroker/tasks/list.go create mode 100644 pkg/cloudbroker/tasks/models.go create mode 100644 pkg/cloudbroker/tasks/tasks.go create mode 100644 pkg/cloudbroker/vins/audits.go create mode 100644 pkg/cloudbroker/vins/create_in_account.go create mode 100644 pkg/cloudbroker/vins/create_in_rg.go create mode 100644 pkg/cloudbroker/vins/default_qos_update.go create mode 100644 pkg/cloudbroker/vins/delete.go create mode 100644 pkg/cloudbroker/vins/disable.go create mode 100644 pkg/cloudbroker/vins/enable.go create mode 100644 pkg/cloudbroker/vins/extnet_connect.go create mode 100644 pkg/cloudbroker/vins/extnet_disconnect.go create mode 100644 pkg/cloudbroker/vins/extnet_list.go create mode 100644 pkg/cloudbroker/vins/get.go create mode 100644 pkg/cloudbroker/vins/ip_list.go create mode 100644 pkg/cloudbroker/vins/ip_release.go create mode 100644 pkg/cloudbroker/vins/ip_reserve.go create mode 100644 pkg/cloudbroker/vins/list.go create mode 100644 pkg/cloudbroker/vins/list_deleted.go create mode 100644 pkg/cloudbroker/vins/mass_delete.go create mode 100644 pkg/cloudbroker/vins/mass_disable.go create mode 100644 pkg/cloudbroker/vins/mass_enable.go create mode 100644 pkg/cloudbroker/vins/models.go create mode 100644 pkg/cloudbroker/vins/nat_rule_add.go create mode 100644 pkg/cloudbroker/vins/nat_rule_del.go create mode 100644 pkg/cloudbroker/vins/nat_rule_list.go create mode 100644 pkg/cloudbroker/vins/net_qos.go create mode 100644 pkg/cloudbroker/vins/raise_down.go create mode 100644 pkg/cloudbroker/vins/restore.go create mode 100644 pkg/cloudbroker/vins/search.go create mode 100644 pkg/cloudbroker/vins/vins.go create mode 100644 pkg/cloudbroker/vins/vnfdev_redeploy.go create mode 100644 pkg/cloudbroker/vins/vnfdev_reset.go create mode 100644 pkg/cloudbroker/vins/vnfdev_restart.go create mode 100644 pkg/cloudbroker/vins/vnfdev_start.go create mode 100644 pkg/cloudbroker/vins/vnfdev_stop.go diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0af4a5a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,45 @@ +## Version 1.0.0 + +### Features + +- Add a configurable http-client for interacting with the DECORT cloud platform: + - Custom connection retries + - Custom auth method - app_id, app_secret pair and jwt-token + - Custom parameters for a ssl verify + - Custom SSO URL for auth + - Custom Decort URL for interacting with DECORT +- Add support for a cloudapi api groups: + - account + - bservice + - compute + - computeci + - disks + - extnet + - flipgroup + - image + - k8ci + - k8s + - kvmppc + - kvmx86 + - lb + - locations + - rg + - sizes + - tasks + - vins +- Add support for a cloudbroker api groups: + - account + - compute + - disks + - extnet + - grid + - image + - k8ci + - k8s + - kvmppc + - kvmx86 + - lb + - rg + - sep + - tasks + - vins diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..505d0e0 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +.PHONY: lint +lint: + golangci-lint run --timeout 600s + +.DEFAULT_GOAL := lint \ No newline at end of file diff --git a/README.md b/README.md index b684286..d0b74f2 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,427 @@ # Decort SDK -## Install +Decort SDK - это библиотека, написанная на языке GO, позволяющая взаимодействовать с API облачной платформы **DECORT**. Библиотека содеражит в себе структуры и методы, необходимые для отправки запросов. Decort SDK имеет встроенный http-клиент и поддерживает разные способы авторизации на платформе. Библиотека так же содержит в себе модели ответов от платформы. + +## Оглавление + +- [Установка](#установка) +- [Список API](#список-api) + - [Cloudapi](#cloudapi) + - [Cloudbroker](#cloudbroker) +- [Работа с библиотекой](#работа-с-библиотекой) + - [Настройка конфигурации клиента](#настройка-конфигурации-клиента) + - [Создание клиента](#создание-клиента) + - [Создание структуры запроса](#cоздание-структуры-запроса) + - [Выполнение запроса](#выполнение-запроса) + +## Установка + +Выполните команду в терминале: ```bash go get -u github.com/rudecs/decort-sdk ``` -## Example +## Список API + +Библиотека поддерживает две группы API платформы: + +- `cloudapi` - пользовательская группа, которая позволяет воспользоваться всем стардартным функционалом платформы; +- `cloudbroker` - административная группа, которая позволяет воспользоваться всем стандартным функционалом платформы и расширенными возможностями, включающими в себя управление пользователями, ресурсами, платформами размещения ресурсов и т.д. + +### Cloudapi + +`Cloudapi` позволяет выполнять запросы к группе пользовательских конечных точек +Данная группа ручек позволяет выполнять следующие операции в платформе: + +- `Account` - управление аккаунтами - внутренними учетными записями платформы, которые являются владельцами вычислительных ресурсов; +- `BService` - управление группами виртуальных машин (computes); +- `Compute` - управление виртуальными машинами (индивидуально); +- `ComputeCI` - управление конвейром для создания виртуальных машин; +- `Disks` - управление виртуальными дисками; +- `ExtNet` - управление виртуальными сетями, отвечающими за внешний доступ; +- `FLIPgroup` - управление группами "плавающими" ip - адресами; +- `Image` - управление образами операционных систем; +- `K8CI` - управление конвейром для создания кластера; +- `K8S` - управление кластерами kubernetes; +- `KVMPPC` - создание виртуальной машины Power PC (IBM); +- `KVMx86` - создание виртуальной машины x86; +- `LB` - управление балансировщиками нагрузки; +- `Locations` - получение информации о grid площадки; +- `RG` - управление ресурсными группами аккаунта; +- `Sizes` - получение информации о потребляемых ресурсах виртуальными машинами и дисками; +- `Tasks` - получение информации о ходе выполнения асинхронных задач (например, создание кластера); +- `VINS` - управление виртуальными изолированными сетями. + +### Cloudbroker + +`Cloudbroker` позволяет выполнять запросы к группе пользовательских конечных точек +Данная группа ручек позволяет выполнять следующие операции в платформе: + +- `Account` - управление аккаунтами - внутренними учетными записями платформы, которые являются владельцами вычислительных ресурсов; +- `Compute` - управление виртуальными машинами (индивидуально); +- `Disks` - управление виртуальными дисками; +- `ExtNet` - управление виртуальными сетями, отвечающими за внешний доступ; +- `Grid` - управление площадками; +- `Image` - управление образами операционных систем; +- `K8CI` - управление конвейром для создания кластера; +- `K8S` - управление кластерами kubernetes; +- `KVMPPC` - создание виртуальной машины Power PC (IBM); +- `KVMx86` - создание виртуальной машины x86; +- `LB` - управление балансировщиками нагрузки; +- `RG` - управление ресурсными группами аккаунта; +- `SEP` - управление storage endpoint (sep); +- `Tasks` - получение информации о ходе выполнения асинхронных задач (например, создание кластера); +- `VINS` - управление виртуальными изолированными сетями. + +## Работа с библиотекой + +Алгоритм работы с библиотекой выглядит следующим образом: + +1. Настройка конфигурации клиента. +2. Создание клиента. +3. Создание структуры запроса. +4. Выполнение запроса. + +### Настройка конфигурации клиента + +Сначала, необходимо создать переменную конфигурации клиента. Конфигурация состоит как из обязательных, так и необязательных полей. +| Поле | Тип | Обязательный | Описание | +| --- | --- | --- | --- | +| AppID | string | Да | app_id ключа для выполнения запросов | +| AppSecret | string | Да | app_secret ключ для выполнения запроса | +| SSOURL | string | Да | URL адрес сервиса аутентификации и авторизации | +| DecortURL | string | Да | URL адрес платформы, с которой будет осуществляться взаимодействие | +| Retries | uint | Нет | Кол-во неудачных попыток выполнения запроса, по умолчанию - 5 | +| SSLSkipVerify | bool | Нет | Пропуск проверки подлинности сертификата, по умолчанию - true | +| Token | string | Нет | JWT токен | + +Пример кода: + +```go +import ( + "github.com/rudecs/decort-sdk/config" +) +func main(){ + // Настройка конфигурации + cfg := config.Config{ + AppID: "", + AppSecret: "", + SSOURL: "https://sso.digitalenergy.online", + DecortURL: "https://mr4.digitalenergy.online", + Retries: 5, + } +} +``` + +### Создание клиента + +Создание клиента происходит с помощью функции-строителя `New` из основного пакета `decort-sdk`, для избежания проблем с именами, пакету можно присвоить алиас `decort`. Функция принимает конфигурацию, возвращает структуру `DecortClient`, с помощью которой можно взаимодействовать с платформой. + +### Пример ```go package main import ( - "context" - "fmt" - "log" + "github.com/rudecs/decort-sdk/config" + decort "github.com/rudecs/decort-sdk" +) + +func main() { + // Настройка конфигурации + cfg := config.Config{ + AppID: "", + AppSecret: "", + SSOURL: "https://sso.digitalenergy.online", + DecortURL: "https://mr4.digitalenergy.online", + Retries: 5, + } + + // Создание клиента + client := decort.New(cfg) +} +``` + +### Создание структуры запроса + +Структуры запросов определены в пакетах: + +- `pkg/cloudapi` - для `cloudapi` +- `pkg/cloudbroker` - для `cloudbroker` + +В каждом пакете находятся пакеты групп API: + +- **cloudapi**: + - `pkg/cloudapi/account` - для `Account` + - `pkg/cloudapi/bservice` - для `Basic Service` + - `pkg/cloudapi/compute` - для `Compute` + - `pkg/cloudapi/computeci` - для `ComputeCI` + - `pkg/cloudapi/disks` - для `Disks` + - `pkg/cloudapi/extnet` - для `ExtNet` + - `pkg/cloudapi/flipgroup` - для `FLIPGroup` + - `pkg/cloudapi/image` - для `Image` + - `pkg/cloudapi/k8ci` - для `K8CI` + - `pkg/cloudapi/k8s` - для `K8S` + - `pkg/cloudapi/kvmppc` - для `KVMPPC` + - `pkg/cloudapi/kvmx86` - для `KVMX86` + - `pkg/cloudapi/lb` - для `LB` + - `pkg/cloudapi/locations` - для `Locations` + - `pkg/cloudapi/rg` - для `RG` + - `pkg/cloudapi/sizes` - для `RG` + - `pkg/cloudapi/tasks` - для `Tasks` + - `pkg/cloudapi/vins` - для `VINS` +- **cloudbroker**: + - `pkg/cloudbroker/account` - для `Account` + - `pkg/cloudbroker/compute` - для `Compute` + - `pkg/cloudbroker/disks` - для `Disks` + - `pkg/cloudbroker/extnet` - для `ExtNet` + - `pkg/cloudbroker/grid` - для `Grid` + - `pkg/cloudbroker/image` - для `Image` + - `pkg/cloudbroker/k8ci` - для `K8CI` + - `pkg/cloudbroker/k8s` - для `K8S` + - `pkg/cloudbroker/kvmppc` - для `KVMPPC` + - `pkg/cloudbroker/kvmx86` - для `KVMX86` + - `pkg/cloudbroker/lb` - для `LB` + - `pkg/cloudbroker/rg` - для `RG` + - `pkg/cloudbroker/sep` - для `SEP` + - `pkg/cloudbroker/tasks` - для `Tasks` + - `pkg/cloudbroker/vins` - для `VINS` + +Все поля структуры имеют описание, в которых содержится: + +- Их назначение; +- Обязательный или нет - поле required в комментариях; +- Доп. информация (допустимые значения, значения по умолчанию). + +#### Пример комментарие структуры + +```go +type CreateRequest struct { + // ID of the resource group, which will own this VM + // Required: true + RGID uint64 `url:"rgId"` + + // Name of this VM. + // Must be unique among all VMs (including those in DELETED state) in target resource group + // Required: true + Name string `url:"name"` + + // Number CPUs to allocate to this VM + // Required: true + CPU uint64 `url:"cpu"` + + // Volume of RAM in MB to allocate to this VM + // Required: true + RAM uint64 `url:"ram"` + + // ID of the OS image to base this VM on; + // Could be boot disk image or CD-ROM image + // Required: true + ImageID uint64 `url:"imageId"` + + // Size of the boot disk in GB + // Required: false + BootDisk uint64 `url:"bootDisk,omitempty"` + + // ID of SEP to create boot disk on. + // Uses images SEP ID if not set + // Required: false + SEPID uint64 `url:"sepId,omitempty"` + + // Pool to use if SEP ID is set, can be also empty if needed to be chosen by system + // Required: false + Pool string `url:"pool,omitempty"` - "github.com/rudecs/decort-sdk/config" - "github.com/rudecs/decort-sdk/pkg/cloudapi/kvmx86" + // Network type + // Should be one of: + // - VINS + // - EXTNET + // - NONE + // Required: false + NetType string `url:"netType,omitempty"` + + // Network ID for connect to, + // for EXTNET - external network ID, + // for VINS - VINS ID, + // when network type is not "NONE" + // Required: false + NetID uint64 `url:"netId,omitempty"` + + // IP address to assign to this VM when connecting to the specified network + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // Input data for cloud-init facility + // Required: false + Userdata string `url:"userdata,omitempty"` + + // Text description of this VM + // Required: false + Description string `url:"desc,omitempty"` + + // Start VM upon success + // Required: false + Start bool `url:"start,omitempty"` + + // Stack ID + // Required: false + StackID uint64 `url:"stackId,omitempty"` + + // System name + // Required: false + IS string `url:"IS,omitempty"` + + // Compute purpose + // Required: false + IPAType string `url:"ipaType,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} +``` + +#### Пример создания запроса для развертывания виртуальной машины: + +```go +package main + +import ( + "github.com/rudecs/decort-sdk/config" + decort "github.com/rudecs/decort-sdk" + "github.com/rudecs/decort-sdk/pkg/cloudapi/kvmx86" ) func main() { - cfg := config.Config{ - AppID: "", - AppSecret: "", - SSOURL: "https://sso.digitalenergy.online", - DecortURL: "https://mr4.digitalenergy.online", - Retries: 5, - } - client := decort.New(cfg) - req := kvmx86.CreateRequest{ - RGID: 123, - Name: "compute", - CPU: 4, - RAM: 4096, - ImageID: 321, - } - - res, err := client.KVMX86().Create(context.Background(), req) - if err != nil { - log.Fatal(err) - } - - fmt.Println(res) + // Настройка конфигурации + cfg := config.Config{ + AppID: "", + AppSecret: "", + SSOURL: "https://sso.digitalenergy.online", + DecortURL: "https://mr4.digitalenergy.online", + Retries: 5, + } + + // Создание клиента + client := decort.New(cfg) + + // Создание структуры запроса + // CreateRequest - реквест на создание виртуальной машины + req := kvmx86.CreateRequest{ + RGID: 123, + Name: "compute", + CPU: 4, + RAM: 4096, + ImageID: 321, + } +} +``` + +### Выполнение запроса + +Чтобы выполнить запрос, необходимо: + +1. Вызвать у клиента метод, отвечаеющий за определение группы API для взаимодействия, это может быть `.CloudAPI()`, либо `.CloudBroker()`. Данные методы возвращаеют соответствующие структуры, с помощью которых можно соверать запросы. +2. Вызвать у возвращенной структуры метод, определяющий группу ручек для взаимодействия. + + Доступные методы для `.CloudAPI()`: + + - `.Account()` - для работы с `Account` + - `.BService()` - для работы с `BService` + - `.Compute()` - для работы с `Compute` + - `.ComputeCI()` - для работы с `ComputeCI` + - `.Disks()` - для работы с `Disks` + - `.ExtNet()` - для работы с `ExtNet` + - `.FLIPgroup()` - для работы с `FLIPGroup` + - `.Image()` - для работы с `Image` + - `.K8CI()` - для работы с `K8CI` + - `.K8S()` - для работы с `K8S` + - `.KVMPPC()` - для работы с `KVMPPC` + - `.KVMx86()` - для работы с `KVMX86` + - `.LB()` - для работы с `LB` + - `.Locations()` - для работы с `Locations` + - `.RG()` - для работы с `RG` + - `.Sizes()` - для работы с `Sizes` + - `.Tasks()` - для работы с `Tasks` + - `.VINS()` - для работы с `VINS` + + Доступные методы для `.CloudBroker()`: + + - `.Account()` - для работы с `Account` + - `.Compute()` - для работы с `Compute` + - `.Disks()` - для работы с `Disks` + - `.ExtNet()` - для работы с `ExtNet` + - `.Grid()` - для работы с `Grid` + - `.Image()` - для работы с `Image` + - `.K8CI()` - для работы с `K8CI` + - `.K8S()` - для работы с `K8S` + - `.KVMPPC()` - для работы с `KVMPPC` + - `.KVMx86()` - для работы с `KVMX86` + - `.LB()` - для работы с `LB` + - `.RG()` - для работы с `RG` + - `.SEP()` - для работы с `SEP` + - `.Tasks()` - для работы с `Tasks` + - `.VINS()` - для работы с `VINS` + +3. Вызвать метод, отвечающий за выполнение запроса и передать в него: + +- контекст; +- структуру запроса. + У кождой группы ручек API имеются свои доступные методы, которые определяются платформой. + +4. Обработать результат и ошибки. + +Т.к. все вызовы методов идут последовательно, можно их объеденить в конвейер: +Общий вид вонвейра будет выглядеть так: + +```go + client..<группа>.<метод> +``` + +#### Пример выполнения запроса + +```go +package main + +import ( + "log" + "fmt" + + "github.com/rudecs/decort-sdk/config" + decort "github.com/rudecs/decort-sdk" + "github.com/rudecs/decort-sdk/pkg/cloudapi/kvmx86" +) + +func main() { + // Настройка конфигурации + cfg := config.Config{ + AppID: "", + AppSecret: "", + SSOURL: "https://sso.digitalenergy.online", + DecortURL: "https://mr4.digitalenergy.online", + Retries: 5, + } + + // Создание клиента + client := decort.New(cfg) + + // Создание структуры запроса + // CreateRequest - реквест на создание виртуальной машины + req := kvmx86.CreateRequest{ + RGID: 123, + Name: "compute", + CPU: 4, + RAM: 4096, + ImageID: 321, + } + + //Выполнение запроса с помощью конвейера + res, err := client.СloudAPI().KVMX86().Create(context.Background(), req) + if err != nil { + log.Fatal(err) + } + + fmt.Println(res) } ``` diff --git a/README_EN.md b/README_EN.md new file mode 100644 index 0000000..49852a5 --- /dev/null +++ b/README_EN.md @@ -0,0 +1,62 @@ +# Decort SDK + +Decort SDK is a library, written in GO (Golang) for interact with the **DECORT** API. +The library contents structures and methods for requesting to an user (cloudapi) and admin (cloudbroker) groups of API. +Also the library have structures for responses. + +## Contents + +- [Install](#install) +- [API List](#api-list) +- [Examples](#examples) +- [Examples2](#examples2) + +## Install + +```bash +go get -u github.com/rudecs/decort-sdk +``` + +## API List + +## Examples + +```go +package main + +import ( + "context" + "fmt" + "log" + + "github.com/rudecs/decort-sdk/config" + "github.com/rudecs/decort-sdk/pkg/cloudapi/kvmx86" +) + +func main() { + cfg := config.Config{ + AppID: "", + AppSecret: "", + SSOURL: "https://sso.digitalenergy.online", + DecortURL: "https://mr4.digitalenergy.online", + Retries: 5, + } + client := decort.New(cfg) + req := kvmx86.CreateRequest{ + RGID: 123, + Name: "compute", + CPU: 4, + RAM: 4096, + ImageID: 321, + } + + res, err := client.KVMX86().Create(context.Background(), req) + if err != nil { + log.Fatal(err) + } + + fmt.Println(res) +} +``` + +## Examples2 diff --git a/client.go b/client.go index e7c85ea..3407585 100644 --- a/client.go +++ b/client.go @@ -15,31 +15,36 @@ import ( "github.com/rudecs/decort-sdk/internal/client" ) -type Client struct { +// HTTP-client for platform +type DecortClient struct { decortURL string client *http.Client } -func New(cfg config.Config) *Client { +// Сlient builder +func New(cfg config.Config) *DecortClient { if cfg.Retries == 0 { cfg.Retries = 5 } - return &Client{ + return &DecortClient{ decortURL: cfg.DecortURL, client: client.NewHttpClient(cfg), } } -func (dc *Client) CloudApi() *cloudapi.CloudApi { +// CloudAPI builder +func (dc *DecortClient) CloudAPI() *cloudapi.CloudAPI { return cloudapi.New(dc) } -func (dc *Client) CloudBroker() *cloudbroker.CloudBroker { +// CloudBroker builder +func (dc *DecortClient) CloudBroker() *cloudbroker.CloudBroker { return cloudbroker.New(dc) } -func (dc *Client) DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error) { +// DecortApiCall method for sending requests to the platform +func (dc *DecortClient) DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error) { values, err := query.Values(params) if err != nil { return nil, err diff --git a/config/config.go b/config/config.go index 4a079a4..796e867 100644 --- a/config/config.go +++ b/config/config.go @@ -1,11 +1,39 @@ package config +// Configuration for creating request to platform type Config struct { - Token string - AppID string - AppSecret string - SSOURL string - DecortURL string - Retries uint64 + // JWT platform token + // Required: false + // Example: "qwqwdfwv68979we0q9bfv7e9sbvd89798qrwv97ff" + Token string + + // Application (client) identifier for authorization + // in the cloud platform controller in oauth2 mode. + // Required: true + // Example: "ewqfrvea7s890avw804389qwguf234h0otfi3w4eiu" + AppID string + + // Application (client) secret code for authorization + // in the cloud platform controller in oauth2 mode. + // Example: "frvet09rvesfis0c9erv9fsov0vsdfi09ovds0f" + AppSecret string + + // Platform authentication service address + // Required: true + // Example: "https://sso.digitalenergy.online" + SSOURL string + + // The address of the platform on which the actions are planned + // Required: true + // Example: "https://mr4.digitalenergy.online" + DecortURL string + + // Amount platform request attempts + // Default value: 5 + // Required: false + Retries uint64 + + // Skip verify, true by default + // Required: false SSLSkipVerify bool } diff --git a/interfaces/caller.go b/interfaces/caller.go index 4c987b3..82e4307 100644 --- a/interfaces/caller.go +++ b/interfaces/caller.go @@ -2,6 +2,8 @@ package interfaces import "context" +// Interface for sending requests to platform type Caller interface { + // DecortApiCall method for sending requests to the platform DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error) } diff --git a/pkg/cloudapi/account.go b/pkg/cloudapi/account.go index 79bff01..b8caa47 100644 --- a/pkg/cloudapi/account.go +++ b/pkg/cloudapi/account.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudapi/account" ) -func (ca *CloudApi) Account() *account.Account { +// Accessing the Account method group +func (ca *CloudAPI) Account() *account.Account { return account.New(ca.client) } diff --git a/pkg/cloudapi/account/account.go b/pkg/cloudapi/account/account.go index a01d8a8..f39188a 100644 --- a/pkg/cloudapi/account/account.go +++ b/pkg/cloudapi/account/account.go @@ -1,13 +1,16 @@ +// API Actor API for managing account package account import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to account type Account struct { client interfaces.Caller } +// Builder for account endpoints func New(client interfaces.Caller) *Account { return &Account{ client, diff --git a/pkg/cloudapi/account/add_user.go b/pkg/cloudapi/account/add_user.go index fedb31d..5a2663d 100644 --- a/pkg/cloudapi/account/add_user.go +++ b/pkg/cloudapi/account/add_user.go @@ -9,25 +9,34 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for adding permission to access to account for a user type AddUserRequest struct { - AccountID uint64 `url:"accountId"` - UserID string `url:"userId"` + // ID of account to add to + // Required: true + AccountID uint64 `url:"accountId"` + + // Name of the user to be given rights + // Required: true + UserID string `url:"userId"` + + // Account permission types: + // - 'R' for read only access + // - 'RCX' for Write + // - 'ARCXDU' for Admin + // Required: true AccessType string `url:"accesstype"` } -func (arq AddUserRequest) Validate() error { +func (arq AddUserRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } - if arq.UserID == "" { return errors.New("validation-error: field UserID can not be empty") } - if arq.AccessType == "" { return errors.New("validation-error: field AccessType can not be empty") } - isValid := validators.StringInSlice(arq.AccessType, []string{"R", "RCX", "ARCXDU"}) if !isValid { return errors.New("validation-error: field AccessType can be only R, RCX or ARCXDU") @@ -36,8 +45,9 @@ func (arq AddUserRequest) Validate() error { return nil } +// AddUser gives a user access rights. func (a Account) AddUser(ctx context.Context, req AddUserRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/account/audits.go b/pkg/cloudapi/account/audits.go index b8d0b93..63353c6 100644 --- a/pkg/cloudapi/account/audits.go +++ b/pkg/cloudapi/account/audits.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for give list account audits type AuditsRequest struct { + // ID of the account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq AuditsRequest) Validate() error { +func (arq AuditsRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -19,25 +22,26 @@ func (arq AuditsRequest) Validate() error { return nil } -func (a Account) Audits(ctx context.Context, req AuditsRequest) (AccountAuditsList, error) { - err := req.Validate() +// Audits gets audit records for the specified account object +func (a Account) Audits(ctx context.Context, req AuditsRequest) (ListAudits, error) { + err := req.validate() if err != nil { return nil, err } url := "/cloudapi/account/audits" - auditsRaw, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - audits := AccountAuditsList{} + list := ListAudits{} - err = json.Unmarshal(auditsRaw, &audits) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return audits, nil + return list, nil } diff --git a/pkg/cloudapi/account/create.go b/pkg/cloudapi/account/create.go index 542b50c..ba0f5f3 100644 --- a/pkg/cloudapi/account/create.go +++ b/pkg/cloudapi/account/create.go @@ -5,35 +5,87 @@ import ( "errors" "net/http" "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for creating account type CreateRequest struct { - Name string `url:"name"` - Username string `url:"username"` - EmailAddress string `url:"emailaddress,omitempty"` - MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` - MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` - MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + // Display name + // Required: true + Name string `url:"name"` + + // Name of the account + // Required: true + Username string `url:"username"` + + // Email + // Required: false + EmailAddress string `url:"emailaddress,omitempty"` + + // Max size of memory in MB + // Required: false + MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` + + // Max size of aggregated vdisks in GB + // Required: false + MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` + + // Max number of CPU cores + // Required: false + MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + + // Max sent/received network transfer peering + // Required: false MaxNetworkPeerTransfer uint64 `url:"maxNetworkPeerTransfer,omitempty"` - MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"` - SendAccessEmails bool `url:"sendAccessEmails,omitempty"` - GPUUnits uint64 `url:"gpu_units,omitempty"` + + // Max number of assigned public IPs + // Required: false + MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"` + + // If true send emails when a user is granted access to resources + // Required: false + SendAccessEmails bool `url:"sendAccessEmails,omitempty"` + + // Limit (positive) or disable (0) GPU resources + // Required: false + GPUUnits uint64 `url:"gpu_units,omitempty"` + + // Resource types available to create in this account + // Each element in a resource type slice must be one of: + // - compute + // - vins + // - k8s + // - openshift + // - lb + // - flipgroup + // Required: false + ResTypes []string `url:"resourceTypes,omitempty"` } -func (arq CreateRequest) Validate() error { +func (arq CreateRequest) validate() error { if arq.Name == "" { return errors.New("validation-error: field Name can not be empty") } - if arq.Username == "" { return errors.New("validation-error: field Username can not be empty") } + if len(arq.ResTypes) > 0 { + for _, value := range arq.ResTypes { + validate := validators.StringInSlice(value, []string{"compute", "vins", "k8s", "openshift", "lb", "flipgroup"}) + if !validate { + return errors.New("validation-error: Every resource type specified should be one of [compute, vins, k8s, openshift, lb, flipgroup]") + } + } + } return nil } +// Create creates account +// Setting a cloud unit maximum to -1 or empty will not put any restrictions on the resource func (a Account) Create(ctx context.Context, req CreateRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } diff --git a/pkg/cloudapi/account/delete.go b/pkg/cloudapi/account/delete.go index 7673095..3ebcdfd 100644 --- a/pkg/cloudapi/account/delete.go +++ b/pkg/cloudapi/account/delete.go @@ -6,21 +6,27 @@ import ( "net/http" ) +// Request struct for delete account type DeleteRequest struct { - AccountID uint64 `url:"accountId"` - Permanently bool `url:"permanently,omitempty"` -} + // ID of account to delete + // Required: true + AccountID uint64 `url:"accountId"` -func (arq DeleteRequest) Validate() error { + // Whether to completely delete the account + // Required: false + Permanently bool `url:"permanently,omitempty"` +} +func (arq DeleteRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } return nil } +// Delete completes delete an account from the system Returns true if account is deleted or was already deleted or never existed func (a Account) Delete(ctx context.Context, req DeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/account/delete_user.go b/pkg/cloudapi/account/delete_user.go index 409c144..1f356ea 100644 --- a/pkg/cloudapi/account/delete_user.go +++ b/pkg/cloudapi/account/delete_user.go @@ -7,17 +7,25 @@ import ( "strconv" ) +// Request struct for revoke access to account type DeleteUserRequest struct { - AccountID uint64 `url:"accountId"` - UserID string `url:"userId"` - RecursiveDelete bool `url:"recursivedelete,omitempty"` + // ID of the account + // Required: true + AccountID uint64 `url:"accountId"` + + // ID or emailaddress of the user to remove + // Required: true + UserID string `url:"userId"` + + // Recursively revoke access rights from owned cloudspaces and vmachines + // Required: false + RecursiveDelete bool `url:"recursivedelete,omitempty"` } -func (arq DeleteUserRequest) Validate() error { +func (arq DeleteUserRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } - if arq.UserID == "" { return errors.New("validation-error: field UserID can not be empty") } @@ -25,8 +33,9 @@ func (arq DeleteUserRequest) Validate() error { return nil } +// DeleteUser revokes user access from the account func (a Account) DeleteUser(ctx context.Context, req DeleteUserRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/account/disable_enable.go b/pkg/cloudapi/account/disable_enable.go index 8b2a938..5f46eeb 100644 --- a/pkg/cloudapi/account/disable_enable.go +++ b/pkg/cloudapi/account/disable_enable.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for change status of account type DisabelEnableRequest struct { + // ID of account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq DisabelEnableRequest) Validate() error { +func (arq DisabelEnableRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (arq DisabelEnableRequest) Validate() error { return nil } +// Disable disables an account func (a Account) Disable(ctx context.Context, req DisabelEnableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -40,8 +44,9 @@ func (a Account) Disable(ctx context.Context, req DisabelEnableRequest) (bool, e return result, nil } +// Enable enables an account func (a Account) Enable(ctx context.Context, req DisabelEnableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/account/get.go b/pkg/cloudapi/account/get.go index c7dd5d5..dc99d8e 100644 --- a/pkg/cloudapi/account/get.go +++ b/pkg/cloudapi/account/get.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get information about account type GetRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq GetRequest) Validate() error { +func (arq GetRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (arq GetRequest) Validate() error { return nil } -func (a Account) Get(ctx context.Context, req GetRequest) (*AccountWithResources, error) { - err := req.Validate() +// Get gets account details +func (a Account) Get(ctx context.Context, req GetRequest) (*RecordAccount, error) { + err := req.validate() if err != nil { return nil, err } @@ -32,13 +36,13 @@ func (a Account) Get(ctx context.Context, req GetRequest) (*AccountWithResources return nil, err } - account := &AccountWithResources{} + info := RecordAccount{} - err = json.Unmarshal(res, &account) + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return account, nil + return &info, nil } diff --git a/pkg/cloudapi/account/get_consumed_account_units.go b/pkg/cloudapi/account/get_consumed_account_units.go index 5c31f0e..412797f 100644 --- a/pkg/cloudapi/account/get_consumed_account_units.go +++ b/pkg/cloudapi/account/get_consumed_account_units.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for calculate the currently consumed units for all cloudspaces and resource groups in the account type GetConsumedAccountUnitsRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq GetConsumedAccountUnitsRequest) Validate() error { +func (arq GetConsumedAccountUnitsRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -19,8 +22,14 @@ func (arq GetConsumedAccountUnitsRequest) Validate() error { return nil } +// GetConsumedAccountUnits calculates the currently consumed units for all cloudspaces and resource groups in the account. +// Calculated cloud units are returned in a dict which includes: +// - CU_M: consumed memory in MB +// - CU_C: number of cpu cores +// - CU_D: consumed vdisk storage in GB +// - CU_I: number of public IPs func (a Account) GetConsumedAccountUnits(ctx context.Context, req GetConsumedAccountUnitsRequest) (*ResourceLimits, error) { - err := req.Validate() + err := req.validate() if err != nil { return nil, err } @@ -32,13 +41,12 @@ func (a Account) GetConsumedAccountUnits(ctx context.Context, req GetConsumedAcc return nil, err } - rl := &ResourceLimits{} + info := ResourceLimits{} - err = json.Unmarshal(res, &rl) + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return rl, nil - + return &info, nil } diff --git a/pkg/cloudapi/account/get_consumed_cloud_units_by_type.go b/pkg/cloudapi/account/get_consumed_cloud_units_by_type.go index 1735446..c7862fc 100644 --- a/pkg/cloudapi/account/get_consumed_cloud_units_by_type.go +++ b/pkg/cloudapi/account/get_consumed_cloud_units_by_type.go @@ -9,20 +9,24 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for calculate the currently consumed cloud units of the specified type for all cloudspaces and resource groups in the account type GetConsumedCloudUnitsByTypeRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` - CUType string `url:"cutype"` + + // Cloud unit resource type + // Required: true + CUType string `url:"cutype"` } -func (arq GetConsumedCloudUnitsByTypeRequest) Validate() error { +func (arq GetConsumedCloudUnitsByTypeRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } - if arq.CUType == "" { return errors.New("validation-error: field CUType can not be empty") } - isValid := validators.StringInSlice(arq.CUType, []string{"CU_M", "CU_C", "CU_D", "CU_S", "CU_A", "CU_NO", "CU_I", "CU_NP"}) if !isValid { return errors.New("validation-error: field AccessType can be only CU_M, CU_C, CU_D, CU_S, CU_A, CU_NO, CU_I or CU_NP") @@ -31,8 +35,20 @@ func (arq GetConsumedCloudUnitsByTypeRequest) Validate() error { return nil } +// GetConsumedCloudUnitsByType calculates the currently consumed cloud units of the specified type for all cloudspaces +// and resource groups in the account. +// Possible types of cloud units are include: +// +// - CU_M: returns consumed memory in MB +// - CU_C: returns number of virtual cpu cores +// - CU_D: returns consumed virtual disk storage in GB +// - CU_S: returns consumed primary storage (NAS) in TB +// - CU_A: returns consumed secondary storage (Archive) in TB +// - CU_NO: returns sent/received network transfer in operator in GB +// - CU_NP: returns sent/received network transfer peering in GB +// - CU_I: returns number of public IPs func (a Account) GetConsumedCloudUnitsByType(ctx context.Context, req GetConsumedCloudUnitsByTypeRequest) (float64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } @@ -50,5 +66,4 @@ func (a Account) GetConsumedCloudUnitsByType(ctx context.Context, req GetConsume } return result, nil - } diff --git a/pkg/cloudapi/account/get_consumption.go b/pkg/cloudapi/account/get_consumption.go index 6d375aa..7f4c5b0 100644 --- a/pkg/cloudapi/account/get_consumption.go +++ b/pkg/cloudapi/account/get_consumption.go @@ -6,21 +6,28 @@ import ( "net/http" ) +// Request struct for download the resources tracking files for an account type GetConsumtionRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` - Start uint64 `url:"start"` - End uint64 `url:"end"` + + // Epoch represents the start time + // Required: true + Start uint64 `url:"start"` + + // Epoch represents the end time + // Required: true + End uint64 `url:"end"` } -func (arq GetConsumtionRequest) Validate() error { +func (arq GetConsumtionRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } - if arq.Start == 0 { return errors.New("validation-error: field Start can not be empty or equal to 0") } - if arq.End == 0 { return errors.New("validation-error: field End can not be empty or equal to 0") } @@ -28,8 +35,9 @@ func (arq GetConsumtionRequest) Validate() error { return nil } +// GetConsumtion downloads the resources tracking files for an account within a given period func (a Account) GetConsumtion(ctx context.Context, req GetConsumtionRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } @@ -45,21 +53,19 @@ func (a Account) GetConsumtion(ctx context.Context, req GetConsumtionRequest) (s } +// GetConsumtionGet downloads the resources tracking files for an account within a given period func (a Account) GetConsumtionGet(ctx context.Context, req GetConsumtionRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } - url := "/account/getConsumtion" - prefix := "/cloudapi" + url := "/cloudapi//account/getConsumtion" - url = prefix + url res, err := a.client.DecortApiCall(ctx, http.MethodGet, url, req) if err != nil { return "", err } return string(res), nil - } diff --git a/pkg/cloudapi/account/get_reserved_account_units.go b/pkg/cloudapi/account/get_reserved_account_units.go index 316c833..9e7a45e 100644 --- a/pkg/cloudapi/account/get_reserved_account_units.go +++ b/pkg/cloudapi/account/get_reserved_account_units.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for calculate the reserved units for all cloudspaces and resource groups in the account type GetReservedAccountUnitsRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq GetReservedAccountUnitsRequest) Validate() error { +func (arq GetReservedAccountUnitsRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -19,8 +22,15 @@ func (arq GetReservedAccountUnitsRequest) Validate() error { return nil } +// GetReservedAccountUnits calculates the reserved units for all cloudspaces and resource groups in the account. +// Calculated cloud units are returned in a dict which includes: +// +// - CU_M: reserved memory in MB +// - CU_C: number of cpu cores +// - CU_D: reserved vdisk storage in GB +// - CU_I: number of public IPs func (a Account) GetReservedAccountUnits(ctx context.Context, req GetReservedAccountUnitsRequest) (*ResourceLimits, error) { - err := req.Validate() + err := req.validate() if err != nil { return nil, err } @@ -32,13 +42,12 @@ func (a Account) GetReservedAccountUnits(ctx context.Context, req GetReservedAcc return nil, err } - rl := &ResourceLimits{} + info := ResourceLimits{} - err = json.Unmarshal(res, &rl) + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return rl, nil - + return &info, nil } diff --git a/pkg/cloudapi/account/list.go b/pkg/cloudapi/account/list.go index b37daf3..4f8caeb 100644 --- a/pkg/cloudapi/account/list.go +++ b/pkg/cloudapi/account/list.go @@ -6,12 +6,19 @@ import ( "net/http" ) +// Request struct for get list of accounts type ListRequest struct { + // Page number + // Required: false Page uint64 `url:"page"` + + // Page size + // Required: false Size uint64 `url:"size"` } -func (a Account) List(ctx context.Context, req ListRequest) (AccountCloudApiList, error) { +// List gets list all accounts the user has access to +func (a Account) List(ctx context.Context, req ListRequest) (ListAccounts, error) { url := "/cloudapi/account/list" res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) @@ -19,13 +26,12 @@ func (a Account) List(ctx context.Context, req ListRequest) (AccountCloudApiList return nil, err } - accountList := AccountCloudApiList{} + list := ListAccounts{} - err = json.Unmarshal(res, &accountList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return accountList, nil - + return list, nil } diff --git a/pkg/cloudapi/account/list_computes.go b/pkg/cloudapi/account/list_computes.go index e46b4ad..6a05d8e 100644 --- a/pkg/cloudapi/account/list_computes.go +++ b/pkg/cloudapi/account/list_computes.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for a get list compute instances type ListComputesRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq ListComputesRequest) Validate() error { +func (arq ListComputesRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (arq ListComputesRequest) Validate() error { return nil } -func (a Account) ListComputes(ctx context.Context, req ListComputesRequest) (AccountComputesList, error) { - err := req.Validate() +// ListComputes gets list all compute instances under specified account, accessible by the user +func (a Account) ListComputes(ctx context.Context, req ListComputesRequest) (ListComputes, error) { + err := req.validate() if err != nil { return nil, err } @@ -32,13 +36,12 @@ func (a Account) ListComputes(ctx context.Context, req ListComputesRequest) (Acc return nil, err } - accountComputesList := AccountComputesList{} + list := ListComputes{} - err = json.Unmarshal(res, &accountComputesList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return accountComputesList, nil - + return list, nil } diff --git a/pkg/cloudapi/account/list_deleted.go b/pkg/cloudapi/account/list_deleted.go index a067061..c9717b3 100644 --- a/pkg/cloudapi/account/list_deleted.go +++ b/pkg/cloudapi/account/list_deleted.go @@ -6,12 +6,19 @@ import ( "net/http" ) +// Request struct for get list deleted accounts type ListDeletedRequest struct { + // Page number + // Required: false Page uint64 `url:"page"` + + // Page size + // Required: false Size uint64 `url:"size"` } -func (a Account) ListDeleted(ctx context.Context, req ListDeletedRequest) (AccountCloudApiList, error) { +// ListDeleted gets list all deleted accounts the user has access to +func (a Account) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListAccounts, error) { url := "/cloudapi/account/listDeleted" res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) @@ -19,13 +26,12 @@ func (a Account) ListDeleted(ctx context.Context, req ListDeletedRequest) (Accou return nil, err } - accountList := AccountCloudApiList{} + list := ListAccounts{} - err = json.Unmarshal(res, &accountList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return accountList, nil - + return list, nil } diff --git a/pkg/cloudapi/account/list_disks.go b/pkg/cloudapi/account/list_disks.go index cabbd94..681efa9 100644 --- a/pkg/cloudapi/account/list_disks.go +++ b/pkg/cloudapi/account/list_disks.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list deleted disks type ListDisksRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq ListDisksRequest) Validate() error { +func (arq ListDisksRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (arq ListDisksRequest) Validate() error { return nil } -func (a Account) ListDisks(ctx context.Context, req ListDisksRequest) (AccountDisksList, error) { - err := req.Validate() +// ListDisks gets list all currently unattached disks under specified account +func (a Account) ListDisks(ctx context.Context, req ListDisksRequest) (ListDisks, error) { + err := req.validate() if err != nil { return nil, err } @@ -32,13 +36,12 @@ func (a Account) ListDisks(ctx context.Context, req ListDisksRequest) (AccountDi return nil, err } - accountDisksList := AccountDisksList{} + list := ListDisks{} - err = json.Unmarshal(res, &accountDisksList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return accountDisksList, nil - + return list, nil } diff --git a/pkg/cloudapi/account/list_flipgroups.go b/pkg/cloudapi/account/list_flipgroups.go index cb7fe93..6425f42 100644 --- a/pkg/cloudapi/account/list_flipgroups.go +++ b/pkg/cloudapi/account/list_flipgroups.go @@ -7,11 +7,14 @@ import ( "net/http" ) -type ListFlipGroupsRequest struct { +// Request struct for get list FLIPGroups +type ListFLIPGroupsRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq ListFlipGroupsRequest) Validate() error { +func (arq ListFLIPGroupsRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (arq ListFlipGroupsRequest) Validate() error { return nil } -func (a Account) ListFlipGroups(ctx context.Context, req ListFlipGroupsRequest) (AccountFlipGroupsList, error) { - err := req.Validate() +// ListFLIPGroups gets list all FLIPGroups under specified account, accessible by the user +func (a Account) ListFLIPGroups(ctx context.Context, req ListFLIPGroupsRequest) (ListFLIPGroups, error) { + err := req.validate() if err != nil { return nil, err } @@ -32,13 +36,12 @@ func (a Account) ListFlipGroups(ctx context.Context, req ListFlipGroupsRequest) return nil, err } - accountFlipGroupsList := AccountFlipGroupsList{} + list := ListFLIPGroups{} - err = json.Unmarshal(res, &accountFlipGroupsList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return accountFlipGroupsList, nil - + return list, nil } diff --git a/pkg/cloudapi/account/list_rg.go b/pkg/cloudapi/account/list_rg.go index 879ec70..3679195 100644 --- a/pkg/cloudapi/account/list_rg.go +++ b/pkg/cloudapi/account/list_rg.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list resource groups type ListRGRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq ListRGRequest) Validate() error { +func (arq ListRGRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (arq ListRGRequest) Validate() error { return nil } -func (a Account) ListRG(ctx context.Context, req ListRGRequest) (AccountRGList, error) { - err := req.Validate() +// ListRG gets list all resource groups under specified account, accessible by the user +func (a Account) ListRG(ctx context.Context, req ListRGRequest) (ListRG, error) { + err := req.validate() if err != nil { return nil, err } @@ -32,13 +36,12 @@ func (a Account) ListRG(ctx context.Context, req ListRGRequest) (AccountRGList, return nil, err } - accountRGList := AccountRGList{} + list := ListRG{} - err = json.Unmarshal(res, &accountRGList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return accountRGList, nil - + return list, nil } diff --git a/pkg/cloudapi/account/list_templates.go b/pkg/cloudapi/account/list_templates.go index fdcf480..50cf63d 100644 --- a/pkg/cloudapi/account/list_templates.go +++ b/pkg/cloudapi/account/list_templates.go @@ -7,12 +7,18 @@ import ( "net/http" ) +// Request struct for get list templates type ListTemplatesRequest struct { - AccountID uint64 `url:"accountId"` - IncludeDeleted bool `url:"includedeleted"` + // ID an account + // Required: true + AccountID uint64 `url:"accountId"` + + // Include deleted images + // Required: false + IncludeDeleted bool `url:"includedeleted"` } -func (arq ListTemplatesRequest) Validate() error { +func (arq ListTemplatesRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -20,8 +26,9 @@ func (arq ListTemplatesRequest) Validate() error { return nil } -func (a Account) ListTemplates(ctx context.Context, req ListTemplatesRequest) (AccountTemplatesList, error) { - err := req.Validate() +// ListTemplates gets list templates which can be managed by this account +func (a Account) ListTemplates(ctx context.Context, req ListTemplatesRequest) (ListTemplates, error) { + err := req.validate() if err != nil { return nil, err } @@ -33,13 +40,12 @@ func (a Account) ListTemplates(ctx context.Context, req ListTemplatesRequest) (A return nil, err } - accountTemplatesList := AccountTemplatesList{} + list := ListTemplates{} - err = json.Unmarshal(res, &accountTemplatesList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return accountTemplatesList, nil - + return list, nil } diff --git a/pkg/cloudapi/account/list_vins.go b/pkg/cloudapi/account/list_vins.go index 394a5b3..d39dde9 100644 --- a/pkg/cloudapi/account/list_vins.go +++ b/pkg/cloudapi/account/list_vins.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list VINS type ListVINSRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq ListVINSRequest) Validate() error { +func (arq ListVINSRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (arq ListVINSRequest) Validate() error { return nil } -func (a Account) ListVINS(ctx context.Context, req ListVINSRequest) (AccountVINSList, error) { - err := req.Validate() +// ListVINS gets list all ViNSes under specified account, accessible by the user +func (a Account) ListVINS(ctx context.Context, req ListVINSRequest) (ListVINS, error) { + err := req.validate() if err != nil { return nil, err } @@ -32,13 +36,12 @@ func (a Account) ListVINS(ctx context.Context, req ListVINSRequest) (AccountVINS return nil, err } - accountVINSList := AccountVINSList{} + list := ListVINS{} - err = json.Unmarshal(res, &accountVINSList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return accountVINSList, nil - + return list, nil } diff --git a/pkg/cloudapi/account/models.go b/pkg/cloudapi/account/models.go index 84e62f8..cc86520 100644 --- a/pkg/cloudapi/account/models.go +++ b/pkg/cloudapi/account/models.go @@ -1,229 +1,547 @@ package account -type AccountACLRecord struct { - IsExplicit bool `json:"explicit"` - GUID string `json:"guid"` - Rights string `json:"right"` - Status string `json:"status"` - Type string `json:"type"` - UgroupID string `json:"userGroupId"` - CanBeDeleted bool `json:"canBeDeleted"` +// Access Control List +type RecordACL struct { + // Whether access is explicitly specified + IsExplicit bool `json:"explicit"` + + // GUID + GUID string `json:"guid"` + + // Access rights + Rights string `json:"right"` + + // Status + Status string `json:"status"` + + // Account Type + Type string `json:"type"` + + // Account owner ID + UgroupID string `json:"userGroupId"` + + // Is it possible to remove + CanBeDeleted bool `json:"canBeDeleted"` } +// Resource limits type ResourceLimits struct { - CUC float64 `json:"CU_C"` - CUD float64 `json:"CU_D"` - CUI float64 `json:"CU_I"` - CUM float64 `json:"CU_M"` - CUNP float64 `json:"CU_NP"` + // Number of cores + CUC float64 `json:"CU_C"` + + // Disk size, GB + CUD float64 `json:"CU_D"` + + // Number of public IP addresses + CUI float64 `json:"CU_I"` + + // RAM size, MB + CUM float64 `json:"CU_M"` + + // Traffic volume, GB + CUNP float64 `json:"CU_NP"` + + // Number of graphics cores GPUUnits float64 `json:"gpu_units"` } -type AccountRecord struct { - DCLocation string `json:"DCLocation"` - CKey string `jspn:"_ckey"` - Meta []interface{} `json:"_meta"` - ACL []AccountACLRecord `json:"acl"` - Company string `json:"company"` - CompanyURL string `json:"companyurl"` - CreatedBy string `jspn:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeactiovationTime float64 `json:"deactivationTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - DisplayName string `json:"displayname"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - Name string `json:"name"` - ResourceLimits ResourceLimits `json:"resourceLimits"` - SendAccessEmails bool `json:"sendAccessEmails"` - ServiceAccount bool `json:"serviceAccount"` - Status string `json:"status"` - UpdatedTime uint64 `json:"updatedTime"` - Version uint64 `json:"version"` - VINS []uint64 `json:"vins"` -} - -type AccountList []AccountRecord - -type AccountCloudApi struct { - ACL []AccountACLRecord `json:"acl"` - CreatedTime uint64 `json:"createdTime"` - DeletedTime uint64 `json:"deletedTime"` - ID uint64 `json:"id"` - Name string `json:"name"` - Status string `json:"status"` - UpdatedTime uint64 `json:"updatedTime"` -} - -type AccountCloudApiList []AccountCloudApi +// Main information of account +type InfoAccount struct { + // Segment + DCLocation string `json:"DCLocation"` + + // Key + CKey string `jspn:"_ckey"` + + // Meta + Meta []interface{} `json:"_meta"` + + // Access Control List + ACL []RecordACL `json:"acl"` + + // Company + Company string `json:"company"` + + // Company URL + CompanyURL string `json:"companyurl"` + + // Created by + CreatedBy string `jspn:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deactiovation time + DeactiovationTime float64 `json:"deactivationTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Display name + DisplayName string `json:"displayname"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Resource Limits + ResourceLimits ResourceLimits `json:"resourceLimits"` + + // If true send emails when a user is granted access to resources + SendAccessEmails bool `json:"sendAccessEmails"` + + // Service Account + ServiceAccount bool `json:"serviceAccount"` + + // Status + Status string `json:"status"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // Version + Version uint64 `json:"version"` + + // List VINS in account + VINS []uint64 `json:"vins"` +} + +// Main information in one of if the list of accounts +type ItemAccount struct { + // Access Control List + ACL []RecordACL `json:"acl"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Status + Status string `json:"status"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` +} + +// List of accounts +type ListAccounts []ItemAccount + +// Resources used type Resource struct { - CPU int64 `json:"cpu"` - DiskSize int64 `json:"disksize"` - ExtIPs int64 `json:"extips"` + // Number of cores + CPU int64 `json:"cpu"` + + // Disk size + DiskSize int64 `json:"disksize"` + + // Number of External IPs + ExtIPs int64 `json:"extips"` + + // External traffic ExtTraffic int64 `json:"exttraffic"` - GPU int64 `json:"gpu"` - RAM int64 `json:"ram"` + + // Number of grafic cores + GPU int64 `json:"gpu"` + + // Number of RAM + RAM int64 `json:"ram"` } +// Information about resources type Resources struct { - Current Resource `json:"Current"` + // Current information about resources + Current Resource `json:"Current"` + + // Reserved information about resources Reserved Resource `json:"Reserved"` } +// Information about computes type Computes struct { + // Number of started computes Started uint64 `json:"started"` + + // Number of stopped computes Stopped uint64 `json:"stopped"` } +// Information about machines type Machines struct { + // Number of running machines Running uint64 `json:"running"` - Halted uint64 `json:"halted"` + + // Number of halted machines + Halted uint64 `json:"halted"` } -type AccountWithResources struct { - Account +// Сomplete information about account +type RecordAccount struct { + // Main information about account + InfoAccount + + // Resources Resources Resources `json:"Resources"` - Computes Computes `json:"computes"` - Machines Machines `json:"machines"` - VINSes uint64 `json:"vinses"` -} - -type AccountCompute struct { - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - CPUs uint64 `json:"cpus"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - ComputeID uint64 `json:"id"` - ComputeName string `json:"name"` - RAM uint64 `json:"ram"` - Registered bool `json:"registered"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` + + // Computes + Computes Computes `json:"computes"` + + // Machines + Machines Machines `json:"machines"` + + // Number of VINSes + VINSes uint64 `json:"vinses"` +} + +// Main information about compute +type ItemCompute struct { + // ID an account + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Number of CPU + CPUs uint64 `json:"cpus"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // ID compute + ComputeID uint64 `json:"id"` + + // Compute name + ComputeName string `json:"name"` + + // Number of RAM + RAM uint64 `json:"ram"` + + // Registered or not + Registered bool `json:"registered"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group Name + RGName string `json:"rgName"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Total disks size TotalDisksSize uint64 `json:"totalDisksSize"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - UserManaged bool `json:"userManaged"` - VINSConnected uint64 `json:"vinsConnected"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // User controlled or not + UserManaged bool `json:"userManaged"` + + // Number of connected VINS + VINSConnected uint64 `json:"vinsConnected"` } -type AccountComputesList []AccountCompute +// List of computes +type ListComputes []ItemCompute + +// Main information about disk +type ItemDisk struct { + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` -type AccountDisk struct { - ID uint64 `json:"id"` - Name string `json:"name"` - Pool string `json:"pool"` - SepID uint64 `json:"sepId"` + // Pool + Pool string `json:"pool"` + + // ID SEP + SEPID uint64 `json:"sepId"` + + // Max size SizeMax uint64 `json:"sizeMax"` - Type string `json:"type"` + + // Disk type + Type string `json:"type"` } -type AccountDisksList []AccountDisk +// List of disks +type ListDisks []ItemDisk -type AccountVIN struct { - AccountID uint64 `json:"accountId"` +// Main information about VINS +type ItemVINS struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Name of account AccountName string `json:"accountName"` - Computes uint64 `json:"computes"` - CreatedBy string `json:"createdBy"` + + // Number of computes + Computes uint64 `json:"computes"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time DeletedTime uint64 `json:"deletedTime"` - ExternalIP string `json:"externalIP"` - ID uint64 `json:"id"` - Name string `json:"name"` - Network string `json:"network"` - PriVnfDevID uint64 `json:"priVnfDevId"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - Status string `json:"status"` - UpdatedBy string `json:"updatedBy"` + + // External IP + ExternalIP string `json:"externalIP"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Network + Network string `json:"network"` + + // NNFDev ID + PriVNFDevID uint64 `json:"priVnfDevId"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Status + Status string `json:"status"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time UpdatedTime uint64 `json:"updatedTime"` } -type AccountVINSList []AccountVIN +// List of VINS +type ListVINS []ItemVINS + +// Main info about audit +type ItemAudit struct { + // Call + Call string `json:"call"` -type AccountAudit struct { - Call string `json:"call"` + // Response time ResponseTime float64 `json:"responsetime"` - StatusCode uint64 `json:"statuscode"` - Timestamp float64 `json:"timestamp"` - User string `json:"user"` + + // Status code + StatusCode uint64 `json:"statuscode"` + + // Timestamp + Timestamp float64 `json:"timestamp"` + + // User + User string `json:"user"` } -type AccountAuditsList []AccountAudit +// List of audits +type ListAudits []ItemAudit + +// Information compute in resource group +type RGComputes struct { + // Number of started computes + Started uint64 `json:"started"` -type AccountRGComputes struct { - Started uint64 `json:"Started"` - Stopped uint64 `json:"Stopped"` + // Number of stopped computes + Stopped uint64 `json:"stopped"` } -type AccountRGResources struct { +// Resources of Resource group +type RGResources struct { + // Consumed Consumed Resource `json:"Consumed"` - Limits Resource `json:"Limits"` + + // Limits + Limits Resource `json:"Limits"` + + // Reserved Reserved Resource `json:"Reserved"` } -type AccountRG struct { - Computes AccountRGComputes `json:"Computes"` - Resources AccountRGResources `json:"Resources"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - RGID uint64 `json:"id"` - Milestones uint64 `json:"milestones"` - RGName string `json:"name"` - Status string `json:"status"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - VINSes uint64 `json:"vinses"` +// Main information about resource group +type ItemRG struct { + // Computes + Computes RGComputes `json:"Computes"` + + // Resources + Resources RGResources `json:"Resources"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Resource group ID + RGID uint64 `json:"id"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Resource group name + RGName string `json:"name"` + + // Status + Status string `json:"status"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // Number of VINS + VINSes uint64 `json:"vinses"` } -type AccountRGList []AccountRG +// List of Resource groups +type ListRG []ItemRG + +// Main information about template +type ItemTemplate struct { + // UNCPath + UNCPath string `json:"UNCPath"` + + // Account ID + AccountID uint64 `json:"accountId"` -type AccountTemplate struct { - UNCPath string `json:"UNCPath"` - AccountID uint64 `json:"accountId"` + // Description Description string `json:"desc"` - ID uint64 `json:"id"` - Name string `json:"name"` - Public bool `json:"public"` - Size uint64 `json:"size"` - Status string `json:"status"` - Type string `json:"type"` - Username string `json:"username"` -} - -type AccountTemplatesList []AccountTemplate - -type AccountFlipGroup struct { - AccountID uint64 `json:"accountId"` - ClientType string `json:"clientType"` - ConnType string `json:"connType"` - CreatedBy string `json:"createdBy"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Public or not + Public bool `json:"public"` + + // Size + Size uint64 `json:"size"` + + // Status + Status string `json:"status"` + + // Type + Type string `json:"type"` + + // Username + Username string `json:"username"` +} + +// List of templates +type ListTemplates []ItemTemplate + +// Main information about FLIPGroup +type ItemFLIPGroup struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Client type + ClientType string `json:"clientType"` + + // Connection type + ConnType string `json:"connType"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time CreatedTime uint64 `json:"createdTime"` - DefaultGW string `json:"defaultGW"` - DeletedBy string `json:"deletedBy"` + + // Default GW + DefaultGW string `json:"defaultGW"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time DeletedTime uint64 `json:"deletedTime"` + + // Description Description string `json:"desc"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - IP string `json:"ip"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - NetID uint64 `json:"netId"` - NetType string `json:"netType"` - NetMask uint64 `json:"netmask"` - Status string `json:"status"` - UpdatedBy string `json:"updatedBy"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // IP + IP string `json:"ip"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Network ID + NetID uint64 `json:"netId"` + + // Network type + NetType string `json:"netType"` + + // Network mask + NetMask uint64 `json:"netmask"` + + // Status + Status string `json:"status"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time UpdatedTime uint64 `json:"updatedTime"` } -type AccountFlipGroupsList []AccountFlipGroup +// List of FLIPGroups +type ListFLIPGroups []ItemFLIPGroup diff --git a/pkg/cloudapi/account/restore.go b/pkg/cloudapi/account/restore.go index bc14300..cea9954 100644 --- a/pkg/cloudapi/account/restore.go +++ b/pkg/cloudapi/account/restore.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for restore a deleted account type RestoreRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq RestoreRequest) Validate() error { +func (arq RestoreRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (arq RestoreRequest) Validate() error { return nil } +// Restore restores a deleted account func (a Account) Restore(ctx context.Context, req RestoreRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -38,5 +42,4 @@ func (a Account) Restore(ctx context.Context, req RestoreRequest) (bool, error) } return result, nil - } diff --git a/pkg/cloudapi/account/update.go b/pkg/cloudapi/account/update.go index 5efeefb..0298850 100644 --- a/pkg/cloudapi/account/update.go +++ b/pkg/cloudapi/account/update.go @@ -5,30 +5,79 @@ import ( "errors" "net/http" "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for updaate account type UpdateRequest struct { - AccountID uint64 `url:"accountId"` - Name string `url:"name,omitempty"` - MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` - MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` - MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + // ID an account + // Required: true + AccountID uint64 `url:"accountId"` + + // Name of the account + // Required: false + Name string `url:"name,omitempty"` + + // Max size of memory in MB + // Required: false + MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` + + // Max size of aggregated vdisks in GB + // Required: false + MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` + + // Max number of CPU cores + // Required: false + MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + + // Max sent/received network transfer peering + // Required: false MaxNetworkPeerTransfer uint64 `url:"maxNetworkPeerTransfer,omitempty"` - MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"` - SendAccessEmails bool `url:"sendAccessEmails,omitempty"` - GPUUnits uint64 `url:"gpu_units,omitempty"` + + // Max number of assigned public IPs + // Required: false + MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"` + + // If true send emails when a user is granted access to resources + // Required: false + SendAccessEmails bool `url:"sendAccessEmails,omitempty"` + + // Limit (positive) or disable (0) GPU resources + // Required: false + GPUUnits uint64 `url:"gpu_units,omitempty"` + + // Resource types available to create in this account + // Each element in a resource type slice must be one of: + // - compute + // - vins + // - k8s + // - openshift + // - lb + // - flipgroup + // Required: false + ResTypes []string `url:"resourceTypes,omitempty"` } -func (arq UpdateRequest) Validate() error { +func (arq UpdateRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } + if len(arq.ResTypes) > 0 { + for _, value := range arq.ResTypes { + validate := validators.StringInSlice(value, []string{"compute", "vins", "k8s", "openshift", "lb", "flipgroup"}) + if !validate { + return errors.New("validation-error: Every resource type specified should be one of [compute, vins, k8s, openshift, lb, flipgroup]") + } + } + } return nil } +// Update updates an account name and resource types and limits func (a Account) Update(ctx context.Context, req UpdateRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/account/update_user.go b/pkg/cloudapi/account/update_user.go index 8949dc2..1b07d79 100644 --- a/pkg/cloudapi/account/update_user.go +++ b/pkg/cloudapi/account/update_user.go @@ -9,25 +9,34 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for update user access rights type UpdateUserRequest struct { - AccountID uint64 `url:"accountId"` - UserID string `url:"userId"` + // ID of the account + // Required: true + AccountID uint64 `url:"accountId"` + + // Userid/Email for registered users or emailaddress for unregistered users + // Required: true + UserID string `url:"userId"` + + // Account permission types: + // - 'R' for read only access + // - 'RCX' for Write + // - 'ARCXDU' for Admin + // Required: true AccessType string `url:"accesstype"` } -func (arq UpdateUserRequest) Validate() error { +func (arq UpdateUserRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } - if arq.UserID == "" { return errors.New("validation-error: field UserID can not be empty") } - if arq.AccessType == "" { return errors.New("validation-error: field AccessType can not be empty") } - isValid := validators.StringInSlice(arq.AccessType, []string{"R", "RCX", "ARCXDU"}) if !isValid { return errors.New("validation-error: field AccessType can be only R, RCX or ARCXDU") @@ -36,8 +45,9 @@ func (arq UpdateUserRequest) Validate() error { return nil } +// UpdateUser updates user access rights func (a Account) UpdateUser(ctx context.Context, req UpdateUserRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/bservice.go b/pkg/cloudapi/bservice.go new file mode 100644 index 0000000..e21d011 --- /dev/null +++ b/pkg/cloudapi/bservice.go @@ -0,0 +1,8 @@ +package cloudapi + +import "github.com/rudecs/decort-sdk/pkg/cloudapi/bservice" + +// Accessing the BService method group +func (ca *CloudAPI) BService() *bservice.BService { + return bservice.New(ca.client) +} diff --git a/pkg/cloudapi/bservice/bservice.go b/pkg/cloudapi/bservice/bservice.go index 0b92cc2..401df71 100644 --- a/pkg/cloudapi/bservice/bservice.go +++ b/pkg/cloudapi/bservice/bservice.go @@ -1,11 +1,14 @@ +// API Actor for managing Compute Group. This actor is a final API for endusers to manage Compute Group package bservice import "github.com/rudecs/decort-sdk/interfaces" +// Structure for creating request to bservice type BService struct { client interfaces.Caller } +// Builder for bservice endpoints func New(client interfaces.Caller) *BService { return &BService{ client, diff --git a/pkg/cloudapi/bservice/create.go b/pkg/cloudapi/bservice/create.go index 1196457..0ae8188 100644 --- a/pkg/cloudapi/bservice/create.go +++ b/pkg/cloudapi/bservice/create.go @@ -7,18 +7,29 @@ import ( "strconv" ) +// Request struct for BasicService type CreateRequest struct { - Name string `url:"name"` - RGID uint64 `url:"rgId"` + // Name of the service + // Required: true + Name string `url:"name"` + + // ID of the Resource Group where this service will be placed + // Required: true + RGID uint64 `url:"rgId"` + + // Name of the user to deploy SSH key for. Pass empty string if no SSH key deployment is required + // Required: false SSHUser string `url:"sshUser,omitempty"` - SSHKey string `url:"sshKey,omitempty"` + + // SSH key to deploy for the specified user. Same key will be deployed to all computes of the service + // Required: false + SSHKey string `url:"sshKey,omitempty"` } -func (bsrq CreateRequest) Validate() error { +func (bsrq CreateRequest) validate() error { if bsrq.Name == "" { return errors.New("field Name can not be empty") } - if bsrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } @@ -26,16 +37,24 @@ func (bsrq CreateRequest) Validate() error { return nil } +// Create creates blank BasicService instance func (b BService) Create(ctx context.Context, req CreateRequest) (uint64, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return 0, err } url := "/cloudapi/bservice/create" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return 0, err } - return strconv.ParseUint(string(res), 10, 64) + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/delete.go b/pkg/cloudapi/bservice/delete.go index 4568f45..bf872dd 100644 --- a/pkg/cloudapi/bservice/delete.go +++ b/pkg/cloudapi/bservice/delete.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for delete basic service type DeleteRequest struct { - ServiceID uint64 `url:"serviceId"` - Permanently bool `url:"permanently,omitempty"` + // ID of the BasicService to be delete + // Required: true + ServiceID uint64 `url:"serviceId"` + + // If set to False, Basic service will be deleted to recycle bin. Otherwise destroyed immediately + // Required: true + Permanently bool `url:"permanently,omitempty"` } -func (bsrq DeleteRequest) Validate() error { +func (bsrq DeleteRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } @@ -20,16 +26,24 @@ func (bsrq DeleteRequest) Validate() error { return nil } +// Delete deletes BasicService instance func (b BService) Delete(ctx context.Context, req DeleteRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/delete" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/disable.go b/pkg/cloudapi/bservice/disable.go index 86b3e40..d19095a 100644 --- a/pkg/cloudapi/bservice/disable.go +++ b/pkg/cloudapi/bservice/disable.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for disable service type DisableRequest struct { + // ID of the service to disable + // Required: true ServiceID uint64 `url:"serviceId"` } -func (bsrq DisableRequest) Validate() error { +func (bsrq DisableRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } @@ -19,16 +22,26 @@ func (bsrq DisableRequest) Validate() error { return nil } +// Disable disables service. +// Disabling a service technically means setting model status +// of all computes and service itself to DISABLED and stopping all computes. func (b BService) Disable(ctx context.Context, req DisableRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/delete" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/enable.go b/pkg/cloudapi/bservice/enable.go index 356d49b..9e664aa 100644 --- a/pkg/cloudapi/bservice/enable.go +++ b/pkg/cloudapi/bservice/enable.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for disable service type EnableRequest struct { + // ID of the service to enable + // Required: true ServiceID uint64 `url:"serviceId"` } -func (bsrq EnableRequest) Validate() error { +func (bsrq EnableRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } @@ -19,16 +22,27 @@ func (bsrq EnableRequest) Validate() error { return nil } +// Enable enables service. +// Enabling a service technically means setting model status of +// all computes and service itself to ENABLED. +// It does not start computes. func (b BService) Enable(ctx context.Context, req EnableRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/enable" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/get.go b/pkg/cloudapi/bservice/get.go index 413d24d..03bfb98 100644 --- a/pkg/cloudapi/bservice/get.go +++ b/pkg/cloudapi/bservice/get.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get detailed information about service type GetRequest struct { + // ID of the service to query information + // Required: true ServiceID uint64 `url:"serviceId"` } -func (bsrq GetRequest) Validate() error { +func (bsrq GetRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } @@ -19,21 +22,26 @@ func (bsrq GetRequest) Validate() error { return nil } -func (b BService) Get(ctx context.Context, req GetRequest) (*BasicService, error) { - if err := req.Validate(); err != nil { +// Get gets detailed specifications for the BasicService. +func (b BService) Get(ctx context.Context, req GetRequest) (*RecordBasicService, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/bservice/get" + bsRaw, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - bs := &BasicService{} - if err := json.Unmarshal(bsRaw, bs); err != nil { + info := RecordBasicService{} + + err = json.Unmarshal(bsRaw, &info) + if err != nil { return nil, err } - return bs, nil + return &info, nil } diff --git a/pkg/cloudapi/bservice/group_add.go b/pkg/cloudapi/bservice/group_add.go index 6e38ad0..069df64 100644 --- a/pkg/cloudapi/bservice/group_add.go +++ b/pkg/cloudapi/bservice/group_add.go @@ -7,50 +7,82 @@ import ( "strconv" ) +// Request struct for create new compute group within BasicService type GroupAddRequest struct { - ServiceID uint64 `url:"serviceId"` - Name string `url:"name"` - Count uint64 `url:"count"` - CPU uint64 `url:"cpu"` - RAM uint64 `url:"ram"` - Disk uint64 `url:"disk"` - ImageID uint64 `url:"imageId"` - Driver string `url:"driver"` - Role string `url:"role,omitempty"` - VINSes []uint64 `url:"vinses,omitempty"` - ExtNets []uint64 `url:"extnets,omitempty"` - TimeoutStart uint64 `url:"timeoutStart"` + // ID of the Basic Service to add a group to + // Required: true + ServiceID uint64 `url:"serviceId"` + + // Name of the Compute Group to add + // Required: true + Name string `url:"name"` + + // Computes number. Defines how many computes must be there in the group + // Required: true + Count uint64 `url:"count"` + + // Compute CPU number. All computes in the group have the same CPU count + // Required: true + CPU uint64 `url:"cpu"` + + // Compute RAM volume in MB. All computes in the group have the same RAM volume + // Required: true + RAM uint64 `url:"ram"` + + // Compute boot disk size in GB + // Required: true + Disk uint64 `url:"disk"` + + // OS image ID to create computes from + // Required: true + ImageID uint64 `url:"imageId"` + + // Compute driver + // should be one of: + // - KVM_X86 + // - KVM_PPC + // Required: true + Driver string `url:"driver"` + + // Group role tag. Can be empty string, does not have to be unique + // Required: false + Role string `url:"role,omitempty"` + + // List of ViNSes to connect computes to + // Required: false + VINSes []uint64 `url:"vinses,omitempty"` + + // List of external networks to connect computes to + // Required: false + ExtNets []uint64 `url:"extnets,omitempty"` + + // Time of Compute Group readiness + // Required: false + TimeoutStart uint64 `url:"timeoutStart"` } -func (bsrq GroupAddRequest) Validate() error { +func (bsrq GroupAddRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.Name == "" { return errors.New("field Name can not be empty") } - if bsrq.Count == 0 { return errors.New("field Count can not be empty or equal to 0") } - if bsrq.CPU == 0 { return errors.New("field CPU can not be empty or equal to 0") } - if bsrq.RAM == 0 { return errors.New("field RAM can not be empty or equal to 0") } - if bsrq.Disk == 0 { return errors.New("field Disk can not be empty or equal to 0") } - if bsrq.ImageID == 0 { return errors.New("field ImageID can not be empty or equal to 0") } - if bsrq.Driver == "" { return errors.New("field Driver can not be empty") } @@ -58,16 +90,26 @@ func (bsrq GroupAddRequest) Validate() error { return nil } +// GroupAdd creates new Compute Group within BasicService. +// Compute Group is NOT started automatically, +// so you need to explicitly start it func (b BService) GroupAdd(ctx context.Context, req GroupAddRequest) (uint64, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return 0, err } url := "/cloudapi/bservice/groupAdd" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return 0, err } - return strconv.ParseUint(string(res), 10, 64) + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/group_compute_remove.go b/pkg/cloudapi/bservice/group_compute_remove.go index c903508..90e11c5 100644 --- a/pkg/cloudapi/bservice/group_compute_remove.go +++ b/pkg/cloudapi/bservice/group_compute_remove.go @@ -7,21 +7,28 @@ import ( "strconv" ) +// Request struct for remove group compute type GroupComputeRemoveRequest struct { - ServiceID uint64 `url:"serviceId"` + // ID of the Basic Service + // Required: true + ServiceID uint64 `url:"serviceId"` + + // ID of the Compute GROUP + // Required: true CompGroupID uint64 `url:"compgroupId"` - ComputeID uint64 `url:"computeId"` + + // ID of the Compute + // Required: true + ComputeID uint64 `url:"computeId"` } -func (bsrq GroupComputeRemoveRequest) Validate() error { +func (bsrq GroupComputeRemoveRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.CompGroupID == 0 { return errors.New("field CompGroupID can not be empty or equal to 0") } - if bsrq.ComputeID == 0 { return errors.New("field ComputeID can not be empty or equal to 0") } @@ -29,16 +36,24 @@ func (bsrq GroupComputeRemoveRequest) Validate() error { return nil } +// GroupComputeRemove makes group compute remove of the Basic Service func (b BService) GroupComputeRemove(ctx context.Context, req GroupComputeRemoveRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/groupComputeRemove" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/group_get.go b/pkg/cloudapi/bservice/group_get.go index 25987e9..44f7c3f 100644 --- a/pkg/cloudapi/bservice/group_get.go +++ b/pkg/cloudapi/bservice/group_get.go @@ -7,16 +7,21 @@ import ( "net/http" ) +// Request struct for get detailed information about Compute Group type GroupGetRequest struct { - ServiceID uint64 `url:"serviceId"` + // ID of the Basic Service of Compute Group + // Required: true + ServiceID uint64 `url:"serviceId"` + + // ID of the Compute Group + // Required: true CompGroupID uint64 `url:"compgroupId"` } -func (bsrq GroupGetRequest) Validate() error { +func (bsrq GroupGetRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.CompGroupID == 0 { return errors.New("field CompGroupID can not be empty or equal to 0") } @@ -24,21 +29,26 @@ func (bsrq GroupGetRequest) Validate() error { return nil } -func (b BService) GroupGet(ctx context.Context, req GroupGetRequest) (*Group, error) { - if err := req.Validate(); err != nil { +// GroupGet gets detailed specifications for the Compute Group +func (b BService) GroupGet(ctx context.Context, req GroupGetRequest) (*RecordGroup, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/bservice/groupGet" - groupRaw, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - group := &Group{} - if err := json.Unmarshal(groupRaw, group); err != nil { + info := RecordGroup{} + + err = json.Unmarshal(res, &info) + if err != nil { return nil, err } - return group, nil + return &info, nil } diff --git a/pkg/cloudapi/bservice/group_parent_add.go b/pkg/cloudapi/bservice/group_parent_add.go index 2e1f666..3597c47 100644 --- a/pkg/cloudapi/bservice/group_parent_add.go +++ b/pkg/cloudapi/bservice/group_parent_add.go @@ -7,21 +7,29 @@ import ( "strconv" ) +// Request struct for add parent Compute Group relation emove parent Compute Group +// relation to the specified Compute Group type GroupParentAddRequest struct { - ServiceID uint64 `url:"serviceId"` + // ID of the Basic Service of Compute Group + // Required: true + ServiceID uint64 `url:"serviceId"` + + // ID of the Compute Group + // Required: true CompGroupID uint64 `url:"compgroupId"` - ParentID uint64 `url:"parentId"` + + // ID of the parent Compute Group to register with the current Compute Group + // Required: true + ParentID uint64 `url:"parentId"` } -func (bsrq GroupParentAddRequest) Validate() error { +func (bsrq GroupParentAddRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.CompGroupID == 0 { return errors.New("field CompGroupID can not be empty or equal to 0") } - if bsrq.ParentID == 0 { return errors.New("field ParentID can not be empty or equal to 0") } @@ -29,16 +37,24 @@ func (bsrq GroupParentAddRequest) Validate() error { return nil } +// GroupParentAdd add parent Compute Group relation to the specified Compute Group func (b BService) GroupParentAdd(ctx context.Context, req GroupParentAddRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/groupParentAdd" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/group_parent_remove.go b/pkg/cloudapi/bservice/group_parent_remove.go index afc77d1..1a398a8 100644 --- a/pkg/cloudapi/bservice/group_parent_remove.go +++ b/pkg/cloudapi/bservice/group_parent_remove.go @@ -7,21 +7,30 @@ import ( "strconv" ) +// Request struct for remove parent Compute Group +// relation to the specified Compute Group type GroupParentRemoveRequest struct { - ServiceID uint64 `url:"serviceId"` + // ID of the Basic Service of Compute Group + // Required: true + ServiceID uint64 `url:"serviceId"` + + // ID of the Compute Group + // Required: true CompGroupID uint64 `url:"compgroupId"` - ParentID uint64 `url:"parentId"` + + // ID of the parent Compute Group + // to remove from the current Compute Group + // Required: true + ParentID uint64 `url:"parentId"` } -func (bsrq GroupParentRemoveRequest) Validate() error { +func (bsrq GroupParentRemoveRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.CompGroupID == 0 { return errors.New("field CompGroupID can not be empty or equal to 0") } - if bsrq.ParentID == 0 { return errors.New("field ParentID can not be empty or equal to 0") } @@ -29,16 +38,24 @@ func (bsrq GroupParentRemoveRequest) Validate() error { return nil } +// GroupParentRemove removes parent Compute Group relation to the specified Compute Group func (b BService) GroupParentRemove(ctx context.Context, req GroupParentRemoveRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/groupParentRemove" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/group_remove.go b/pkg/cloudapi/bservice/group_remove.go index ef2df93..63f2c11 100644 --- a/pkg/cloudapi/bservice/group_remove.go +++ b/pkg/cloudapi/bservice/group_remove.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for destroy the specified Compute Group type GroupRemoveRequest struct { - ServiceID uint64 `url:"serviceId"` + // ID of the Basic Service of Compute Group + // Required: true + ServiceID uint64 `url:"serviceId"` + + // ID of the Compute Group + // Required: true CompGroupID uint64 `url:"compgroupId"` } -func (bsrq GroupRemoveRequest) Validate() error { +func (bsrq GroupRemoveRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.CompGroupID == 0 { return errors.New("field CompGroupID can not be empty or equal to 0") } @@ -24,17 +29,25 @@ func (bsrq GroupRemoveRequest) Validate() error { return nil } +// GroupRemove destroy the specified Compute Group func (b BService) GroupRemove(ctx context.Context, req GroupRemoveRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/groupRemove" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/group_resize.go b/pkg/cloudapi/bservice/group_resize.go index ba420d4..39c7b34 100644 --- a/pkg/cloudapi/bservice/group_resize.go +++ b/pkg/cloudapi/bservice/group_resize.go @@ -9,43 +9,64 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for resize the group type GroupResizeRequest struct { - ServiceID uint64 `url:"serviceId"` + // ID of the Basic Service of Compute Group + // Required: true + ServiceID uint64 `url:"serviceId"` + + // ID of the Compute Group to resize + // Required: true CompGroupID uint64 `url:"compgroupId"` - Count int64 `url:"count"` - Mode string `url:"mode"` + + // Either delta or absolute value of computes + // Required: true + Count int64 `url:"count"` + + // Either delta or absolute value of computes + // Should be one of: + // - ABSOLUTE + // - RELATIVE + // Required: true + Mode string `url:"mode"` } -func (bsrq GroupResizeRequest) Validate() error { +func (bsrq GroupResizeRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.CompGroupID == 0 { return errors.New("field CompGroupID can not be empty or equal to 0") } - if bsrq.Mode == "RELATIVE" && bsrq.Count == 0 { return errors.New("field Count can not be equal to 0 if Mode if 'RELATIVE'") } - - if !validators.StringInSlice(bsrq.Mode, []string{"RELATIVE", "ABSOLUTE"}) { + validate := validators.StringInSlice(bsrq.Mode, []string{"RELATIVE", "ABSOLUTE"}) + if !validate { return errors.New("field Mode can only be one of 'RELATIVE' or 'ABSOLUTE'") } return nil } +// GroupResize resize the group by changing the number of computes func (b BService) GroupResize(ctx context.Context, req GroupResizeRequest) (uint64, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return 0, err } url := "/cloudapi/bservice/groupResize" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return 0, err } - return strconv.ParseUint(string(res), 10, 64) + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/group_start.go b/pkg/cloudapi/bservice/group_start.go index 35b6629..d075e7e 100644 --- a/pkg/cloudapi/bservice/group_start.go +++ b/pkg/cloudapi/bservice/group_start.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for start the specified Compute Group type GroupStartRequest struct { - ServiceID uint64 `url:"serviceId"` + // ID of the Basic Service of Compute Group + // Required: true + ServiceID uint64 `url:"serviceId"` + + // ID of the Compute Group to start + // Required: true CompGroupID uint64 `url:"compgroupId"` } -func (bsrq GroupStartRequest) Validate() error { +func (bsrq GroupStartRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.CompGroupID == 0 { return errors.New("field CompGroupID can not be empty or equal to 0") } @@ -24,16 +29,24 @@ func (bsrq GroupStartRequest) Validate() error { return nil } +// GroupStart starts the specified Compute Group within BasicService func (b BService) GroupStart(ctx context.Context, req GroupStartRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/groupStart" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/group_stop.go b/pkg/cloudapi/bservice/group_stop.go index 155d8fa..57f1f98 100644 --- a/pkg/cloudapi/bservice/group_stop.go +++ b/pkg/cloudapi/bservice/group_stop.go @@ -7,17 +7,25 @@ import ( "strconv" ) +// Request struct for stop the specified Compute Group type GroupStopRequest struct { - ServiceID uint64 `url:"serviceId"` + // ID of the Basic Service of Compute Group + // Required: true + ServiceID uint64 `url:"serviceId"` + + // ID of the Compute Group to stop + // Required: true CompGroupID uint64 `url:"compgroupId"` - Force bool `url:"force,omitempty"` + + // Force stop Compute Group + // Required: true + Force bool `url:"force,omitempty"` } -func (bsrq GroupStopRequest) Validate() error { +func (bsrq GroupStopRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.CompGroupID == 0 { return errors.New("field CompGroupID can not be empty or equal to 0") } @@ -25,16 +33,24 @@ func (bsrq GroupStopRequest) Validate() error { return nil } +// GroupStop stops the specified Compute Group within BasicService func (b BService) GroupStop(ctx context.Context, req GroupStopRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/groupStop" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/group_update.go b/pkg/cloudapi/bservice/group_update.go index 184cf80..76b2e4f 100644 --- a/pkg/cloudapi/bservice/group_update.go +++ b/pkg/cloudapi/bservice/group_update.go @@ -7,22 +7,45 @@ import ( "strconv" ) +// Request struct for update existing Compute group type GroupUpdateRequest struct { - ServiceID uint64 `url:"serviceId"` + // ID of the Basic Service of Compute Group + // Required: true + ServiceID uint64 `url:"serviceId"` + + // ID of the Compute Group + // Required: true CompGroupID uint64 `url:"compgroupId"` - Name string `url:"name,omitempty"` - Role string `url:"role,omitempty"` - CPU uint64 `url:"cpu,omitempty"` - RAM uint64 `url:"ram,omitempty"` - Disk uint64 `url:"disk,omitempty"` - Force bool `url:"force,omitempty"` + + // Specify non-empty string to update Compute Group name + // Required: false + Name string `url:"name,omitempty"` + + // Specify non-empty string to update group role + // Required: false + Role string `url:"role,omitempty"` + + // Specify positive value to set new compute CPU count + // Required: false + CPU uint64 `url:"cpu,omitempty"` + + // Specify positive value to set new compute RAM volume in MB + // Required: false + RAM uint64 `url:"ram,omitempty"` + + // Specify new compute boot disk size in GB + // Required: false + Disk uint64 `url:"disk,omitempty"` + + // Force resize Compute Group + // Required: false + Force bool `url:"force,omitempty"` } -func (bsrq GroupUpdateRequest) Validate() error { +func (bsrq GroupUpdateRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.CompGroupID == 0 { return errors.New("field CompGroupID can not be empty or equal to 0") } @@ -30,16 +53,24 @@ func (bsrq GroupUpdateRequest) Validate() error { return nil } +// GroupUpdate updates existing Compute group within Basic Service and apply new settings to its computes as necessary func (b BService) GroupUpdate(ctx context.Context, req GroupUpdateRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/groupUpdate" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/group_update_extnet.go b/pkg/cloudapi/bservice/group_update_extnet.go index d10b267..77e0c64 100644 --- a/pkg/cloudapi/bservice/group_update_extnet.go +++ b/pkg/cloudapi/bservice/group_update_extnet.go @@ -7,17 +7,25 @@ import ( "strconv" ) +// Request struct for update External Network settings type GroupUpdateExtNetRequest struct { - ServiceID uint64 `url:"serviceId"` - CompGroupID uint64 `url:"compgroupId"` - ExtNets []uint64 `url:"extnets,omitempty"` + // ID of the Basic Service of Compute Group + // Required: true + ServiceID uint64 `url:"serviceId"` + + // ID of the Compute Group + // Required: true + CompGroupID uint64 `url:"compgroupId"` + + // List of Extnets to connect computes + // Required: false + ExtNets []uint64 `url:"extnets,omitempty"` } -func (bsrq GroupUpdateExtNetRequest) Validate() error { +func (bsrq GroupUpdateExtNetRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.CompGroupID == 0 { return errors.New("field CompGroupID can not be empty or equal to 0") } @@ -25,16 +33,24 @@ func (bsrq GroupUpdateExtNetRequest) Validate() error { return nil } +// GroupUpdateExtNet updates External Network settings for the group according to the new list func (b BService) GroupUpdateExtNet(ctx context.Context, req GroupUpdateExtNetRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/groupUpdateExtnet" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/group_update_vins.go b/pkg/cloudapi/bservice/group_update_vins.go index 799aa6d..d6f1a6a 100644 --- a/pkg/cloudapi/bservice/group_update_vins.go +++ b/pkg/cloudapi/bservice/group_update_vins.go @@ -7,17 +7,25 @@ import ( "strconv" ) +// Request struct for update VINS settings type GroupUpdateVINSRequest struct { - ServiceID uint64 `url:"serviceId"` - CompGroupID uint64 `url:"compgroupId"` - VINSes []uint64 `url:"vinses,omitempty"` + // ID of the Basic Service of Compute Group + // Required: true + ServiceID uint64 `url:"serviceId"` + + // ID of the Compute Group + // Required: true + CompGroupID uint64 `url:"compgroupId"` + + // List of ViNSes to connect computes + // Required: false + VINSes []uint64 `url:"vinses,omitempty"` } -func (bsrq GroupUpdateVINSRequest) Validate() error { +func (bsrq GroupUpdateVINSRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.CompGroupID == 0 { return errors.New("field CompGroupID can not be empty or equal to 0") } @@ -25,16 +33,24 @@ func (bsrq GroupUpdateVINSRequest) Validate() error { return nil } +// GroupUpdateVINS update ViNS settings for the group according to the new list func (b BService) GroupUpdateVINS(ctx context.Context, req GroupUpdateVINSRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/groupUpdateVins" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/list.go b/pkg/cloudapi/bservice/list.go index a2e4853..8323ddf 100644 --- a/pkg/cloudapi/bservice/list.go +++ b/pkg/cloudapi/bservice/list.go @@ -6,39 +6,59 @@ import ( "net/http" ) +// Request struct for get list/deleted list BasicService instances type ListRequest struct { + // ID of the account to query for BasicService instances + // Required: false AccountID uint64 `url:"accountId,omitempty"` - RGID uint64 `url:"rgId,omitempty"` - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` + + // ID of the resource group to query for BasicService instances + // Required: false + RGID uint64 `url:"rgId,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (b BService) List(ctx context.Context, req ListRequest) (BasicServiceList, error) { +// List gets list BasicService instances associated with the specified Resource Group +func (b BService) List(ctx context.Context, req ListRequest) (ListBasicServices, error) { url := "/cloudapi/bservice/list" - bsListRaw, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - bsList := BasicServiceList{} - if err := json.Unmarshal(bsListRaw, &bsList); err != nil { + list := ListBasicServices{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return bsList, nil + return list, nil } -func (b BService) ListDeleted(ctx context.Context, req ListRequest) (BasicServiceList, error) { +// ListDeleted gets list deleted BasicService instances associated with the specified Resource Group +func (b BService) ListDeleted(ctx context.Context, req ListRequest) (ListBasicServices, error) { url := "/cloudapi/bservice/listDeleted" - bsListRaw, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - bsList := BasicServiceList{} - if err := json.Unmarshal(bsListRaw, &bsList); err != nil { + list := ListBasicServices{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return bsList, nil + return list, nil } diff --git a/pkg/cloudapi/bservice/models.go b/pkg/cloudapi/bservice/models.go index d6cbdfb..1c1d2a5 100644 --- a/pkg/cloudapi/bservice/models.go +++ b/pkg/cloudapi/bservice/models.go @@ -1,123 +1,334 @@ package bservice -type BasicService struct { - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - BaseDomain string `json:"baseDomain"` - Computes []Compute `json:"computes"` - CPUTotal uint64 `json:"cpuTotal"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - DiskTotal uint64 `json:"diskTotal"` - GID uint64 `json:"gid"` - Groups []uint64 `json:"groups"` - GroupsName []string `json:"groupsName"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - ParentSrvID uint64 `json:"parentSrvId"` - ParentSrvType string `json:"parentSrvType"` - RAMTotal uint64 `json:"ramTotal"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - Snapshots []Snapshot `json:"snapshots"` - SSHKey string `json:"sshKey"` - SSHUser string `json:"sshUser"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - UserManaged bool `json:"userManaged"` +// Detailed info about BasicService +type RecordBasicService struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Base domain + BaseDomain string `json:"baseDomain"` + + // List Computes + Computes ListComputes `json:"computes"` + + // Number of cores + CPUTotal uint64 `json:"cpuTotal"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Amount of disk space used, GB + DiskTotal uint64 `json:"diskTotal"` + + // Grid ID + GID uint64 `json:"gid"` + + // List of Service Compute Group IDs + Groups []uint64 `json:"groups"` + + // List of compute groups by name + GroupsName []string `json:"groupsName"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Parent service ID + ParentSrvID uint64 `json:"parentSrvId"` + + // Parent service type + ParentSrvType string `json:"parentSrvType"` + + // Total amount of RAM, MB + RAMTotal uint64 `json:"ramTotal"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // List of snapshots + Snapshots ListSnapshots `json:"snapshots"` + + // SSH key for connection + SSHKey string `json:"sshKey"` + + // Username for SSH connection + SSHUser string `json:"sshUser"` + + // status + Status string `json:"status"` + + // TechStatus + TechStatus string `json:"techStatus"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // Whether user controlled + UserManaged bool `json:"userManaged"` } -type Compute struct { - CompGroupID uint64 `json:"compgroupId"` +// Main information about Compute +type ItemCompute struct { + // Compute group ID + CompGroupID uint64 `json:"compgroupId"` + + // Compute group name CompGroupName string `json:"compgroupName"` + + // compute group role CompGroupRole string `json:"compgroupRole"` - ID uint64 `json:"id"` - Name string `json:"name"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` } -type Snapshot struct { - GUID string `json:"guid"` - Label string `json:"label"` +// List of Computes +type ListComputes []ItemCompute + +// Main information about Snapshot +type ItemSnapshot struct { + // GUID + GUID string `json:"guid"` + + // Label + Label string `json:"label"` + + // Timestamp Timestamp uint64 `json:"timestamp"` - Valid bool `json:"valid"` + + // Valid or not + Valid bool `json:"valid"` } -type Group struct { - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - Computes []GroupCompute `json:"computes"` - Consistency bool `json:"consistency"` - CPU uint64 `json:"cpu"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - Disk uint64 `json:"disk"` - Driver string `json:"driver"` - ExtNets []uint64 `json:"extnets"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - ImageID uint64 `json:"imageId"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - Parents []uint64 `json:"parents"` - RAM uint64 `json:"ram"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - Role string `json:"role"` - SepID uint64 `json:"sepId"` - SeqNo uint64 `json:"seqNo"` - ServiceID uint64 `json:"serviceId"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - TimeoutStart uint64 `json:"timeoutStart"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - VINSes []uint64 `json:"vinses"` +// List of Snapshots +type ListSnapshots []ItemSnapshot + +// Main information about Group +type RecordGroup struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account Name + AccountName string `json:"accountName"` + + // List of Computes + Computes ListGroupComputes `json:"computes"` + + // Consistency or not + Consistency bool `json:"consistency"` + + // Number of CPU + CPU uint64 `json:"cpu"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Amount of disk + Disk uint64 `json:"disk"` + + // Driver + Driver string `json:"driver"` + + // list of External Network IDs + ExtNets []uint64 `json:"extnets"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Image ID + ImageID uint64 `json:"imageId"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // List of Parent IDs + Parents []uint64 `json:"parents"` + + // Number of RAM, MB + RAM uint64 `json:"ram"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Role + Role string `json:"role"` + + // SEPID + SEPID uint64 `json:"sepId"` + + // Sequence number + SeqNo uint64 `json:"seqNo"` + + // Service ID + ServiceID uint64 `json:"serviceId"` + + // Status + Status string `json:"status"` + + // TechStatus + TechStatus string `json:"techStatus"` + + // Timeout Start + TimeoutStart uint64 `json:"timeoutStart"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // List of VINS IDs + VINSes []uint64 `json:"vinses"` } -type GroupCompute struct { - ID uint64 `json:"id"` +// Main information about Group Compute +type ItemGroupCompute struct { + // ID + ID uint64 `json:"id"` + + // IP Addresses IPAddresses []string `json:"ipAddresses"` - Name string `json:"name"` - OSUsers []OSUser `json:"osUsers"` + + // Name + Name string `json:"name"` + + // List of information about OS Users + OSUsers ListOSUsers `json:"osUsers"` } -type OSUser struct { - Login string `json:"login"` +// List of Group Computes +type ListGroupComputes []ItemGroupCompute + +// Main information about OS User +type ItemOSUser struct { + // Login + Login string `json:"login"` + + // Password Password string `json:"password"` } -type BasicServiceShort struct { - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - BaseDomain string `json:"baseDomain"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - GID uint64 `json:"gid"` - Groups []uint64 `json:"groups"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - Name string `json:"name"` - ParentSrvID uint64 `json:"parentSrvId"` - ParentSrvType string `json:"parentSrvType"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - SSHUser string `json:"sshUser"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - UserManaged bool `json:"userManaged"` +// List of information about OS Users +type ListOSUsers []ItemOSUser + +// Main information about BasicService +type ItemBasicService struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Base domain + BaseDomain string `json:"baseDomain"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Grid ID + GID uint64 `json:"gid"` + + // List of group IDs + Groups []uint64 `json:"groups"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Parent service ID + ParentSrvID uint64 `json:"parentSrvId"` + + // Parent service type + ParentSrvType string `json:"parentSrvType"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // SSH user + SSHUser string `json:"sshUser"` + + // Status + Status string `json:"status"` + + // TechStatus + TechStatus string `json:"techStatus"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // User Managed or not + UserManaged bool `json:"userManaged"` } -type BasicServiceList []BasicServiceShort +// List of BasicServices +type ListBasicServices []ItemBasicService diff --git a/pkg/cloudapi/bservice/restore.go b/pkg/cloudapi/bservice/restore.go index a7ecac2..eedd6f3 100644 --- a/pkg/cloudapi/bservice/restore.go +++ b/pkg/cloudapi/bservice/restore.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for restores BasicService instance type RestoreRequest struct { + // ID of the BasicService to be restored + // Required: true ServiceID uint64 `url:"serviceId"` } -func (bsrq RestoreRequest) Validate() error { +func (bsrq RestoreRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } @@ -19,16 +22,24 @@ func (bsrq RestoreRequest) Validate() error { return nil } +// Restore restores BasicService instance func (b BService) Restore(ctx context.Context, req RestoreRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/restore" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/snapshot_create.go b/pkg/cloudapi/bservice/snapshot_create.go index babe1bc..58b291e 100644 --- a/pkg/cloudapi/bservice/snapshot_create.go +++ b/pkg/cloudapi/bservice/snapshot_create.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for create snapshot type SnapshotCreateRequest struct { + // ID of the Basic Service + // Required: true ServiceID uint64 `url:"serviceId"` - Label string `url:"label"` + + // Label of the snapshot + // Required: true + Label string `url:"label"` } -func (bsrq SnapshotCreateRequest) Validate() error { +func (bsrq SnapshotCreateRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.Label == "" { return errors.New("field Label can not be empty") } @@ -24,16 +29,24 @@ func (bsrq SnapshotCreateRequest) Validate() error { return nil } +// SnapshotCreate create snapshot of the Basic Service func (b BService) SnapshotCreate(ctx context.Context, req SnapshotCreateRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/snapshotCreate" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/snapshot_delete.go b/pkg/cloudapi/bservice/snapshot_delete.go index 2531369..1a335c8 100644 --- a/pkg/cloudapi/bservice/snapshot_delete.go +++ b/pkg/cloudapi/bservice/snapshot_delete.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for delete snapshot type SnapshotDeleteRequest struct { + // ID of the Basic Service + // Required: true ServiceID uint64 `url:"serviceId"` - Label string `url:"label"` + + // Label of the snapshot + // Required: true + Label string `url:"label"` } -func (bsrq SnapshotDeleteRequest) Validate() error { +func (bsrq SnapshotDeleteRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.Label == "" { return errors.New("field Label can not be empty") } @@ -24,16 +29,24 @@ func (bsrq SnapshotDeleteRequest) Validate() error { return nil } +// SnapshotDelete delete snapshot of the Basic Service func (b BService) SnapshotDelete(ctx context.Context, req SnapshotDeleteRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/snapshotDelete" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/snapshot_list.go b/pkg/cloudapi/bservice/snapshot_list.go index 2a1417b..6d77009 100644 --- a/pkg/cloudapi/bservice/snapshot_list.go +++ b/pkg/cloudapi/bservice/snapshot_list.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list existing snapshots type SnapshotListRequest struct { + // ID of the Basic Service + // Required: true ServiceID uint64 `url:"serviceId"` } -func (bsrq SnapshotListRequest) Validate() error { +func (bsrq SnapshotListRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } @@ -19,21 +22,26 @@ func (bsrq SnapshotListRequest) Validate() error { return nil } -func (b BService) SnapshotList(ctx context.Context, req SnapshotListRequest) ([]Snapshot, error) { - if err := req.Validate(); err != nil { +// SnapshotList gets list existing snapshots of the Basic Service +func (b BService) SnapshotList(ctx context.Context, req SnapshotListRequest) (ListSnapshots, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/bservice/snapshotList" - snapshotListRaw, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - snapshotList := []Snapshot{} - if err := json.Unmarshal(snapshotListRaw, &snapshotList); err != nil { + list := ListSnapshots{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return snapshotList, nil + return list, nil } diff --git a/pkg/cloudapi/bservice/snapshot_rollback.go b/pkg/cloudapi/bservice/snapshot_rollback.go index 2fa2903..7202521 100644 --- a/pkg/cloudapi/bservice/snapshot_rollback.go +++ b/pkg/cloudapi/bservice/snapshot_rollback.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for rollback snapshot type SnapshotRollbackRequest struct { + // ID of the Basic Service + // Required: true ServiceID uint64 `url:"serviceId"` - Label string `url:"label"` + + // Label of the snapshot + // Required: true + Label string `url:"label"` } -func (bsrq SnapshotRollbackRequest) Validate() error { +func (bsrq SnapshotRollbackRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } - if bsrq.Label == "" { return errors.New("field Label can not be empty") } @@ -24,16 +29,24 @@ func (bsrq SnapshotRollbackRequest) Validate() error { return nil } +// SnapshotRollback rollback snapshot of the Basic Service func (b BService) SnapshotRollback(ctx context.Context, req SnapshotRollbackRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/snapshotRollback" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/start.go b/pkg/cloudapi/bservice/start.go index 59a3662..5bab844 100644 --- a/pkg/cloudapi/bservice/start.go +++ b/pkg/cloudapi/bservice/start.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for start service type StartRequest struct { + // ID of the service to start + // Required: true ServiceID uint64 `url:"serviceId"` } -func (bsrq StartRequest) Validate() error { +func (bsrq StartRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } @@ -19,16 +22,26 @@ func (bsrq StartRequest) Validate() error { return nil } +// Start starts service. +// Starting a service technically means starting computes from all +// service groups according to group relations func (b BService) Start(ctx context.Context, req StartRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/start" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/bservice/stop.go b/pkg/cloudapi/bservice/stop.go index 497ebb2..b4e456e 100644 --- a/pkg/cloudapi/bservice/stop.go +++ b/pkg/cloudapi/bservice/stop.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for stop service type StopRequest struct { + // ID of the service to stop + // Required: true ServiceID uint64 `url:"serviceId"` } -func (bsrq StopRequest) Validate() error { +func (bsrq StopRequest) validate() error { if bsrq.ServiceID == 0 { return errors.New("field ServiceID can not be empty or equal to 0") } @@ -19,16 +22,26 @@ func (bsrq StopRequest) Validate() error { return nil } +// Stop stops service. +// Stopping a service technically means stopping computes from +// all service groups func (b BService) Stop(ctx context.Context, req StopRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/bservice/stop" + res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/cloudapi.go b/pkg/cloudapi/cloudapi.go index 501bf37..e1f8968 100644 --- a/pkg/cloudapi/cloudapi.go +++ b/pkg/cloudapi/cloudapi.go @@ -1,15 +1,18 @@ +// List of method groups for the user package cloudapi import ( "github.com/rudecs/decort-sdk/interfaces" ) -type CloudApi struct { +// Structure for creating request to CloudAPI groups +type CloudAPI struct { client interfaces.Caller } -func New(client interfaces.Caller) *CloudApi { - return &CloudApi{ +// Builder to get access to CloudAPI +func New(client interfaces.Caller) *CloudAPI { + return &CloudAPI{ client: client, } } diff --git a/pkg/cloudapi/compute.go b/pkg/cloudapi/compute.go index 010d4f7..a3a0b55 100644 --- a/pkg/cloudapi/compute.go +++ b/pkg/cloudapi/compute.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudapi/compute" ) -func (ca *CloudApi) Compute() *compute.Compute { +// Accessing the Compute method group +func (ca *CloudAPI) Compute() *compute.Compute { return compute.New(ca.client) } diff --git a/pkg/cloudapi/compute/affinity_group_check_start.go b/pkg/cloudapi/compute/affinity_group_check_start.go index 108641b..9aaf0c7 100644 --- a/pkg/cloudapi/compute/affinity_group_check_start.go +++ b/pkg/cloudapi/compute/affinity_group_check_start.go @@ -6,12 +6,18 @@ import ( "net/http" ) +// Request struct for check all computes with current affinity label can start type AffinityGroupCheckStartRequest struct { - RGID uint64 `url:"rgId"` + // ID of the resource group + // Required: true + RGID uint64 `url:"rgId"` + + // Affinity group label + // Required: true AffinityLabel string `url:"affinityLabel"` } -func (crq AffinityGroupCheckStartRequest) Validate() error { +func (crq AffinityGroupCheckStartRequest) validate() error { if crq.RGID == 0 { return errors.New("validation-error: field RGID can not be empty or equal to 0") } @@ -22,8 +28,9 @@ func (crq AffinityGroupCheckStartRequest) Validate() error { return nil } +// AffinityGroupCheckStart check all computes with current affinity label can start func (c Compute) AffinityGroupCheckStart(ctx context.Context, req AffinityGroupCheckStartRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } diff --git a/pkg/cloudapi/compute/affinity_label_remove.go b/pkg/cloudapi/compute/affinity_label_remove.go index 521faa6..b39061c 100644 --- a/pkg/cloudapi/compute/affinity_label_remove.go +++ b/pkg/cloudapi/compute/affinity_label_remove.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for clear affinity label for compute type AffinityLabelRemoveRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq AffinityLabelRemoveRequest) Validate() error { +func (crq AffinityLabelRemoveRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq AffinityLabelRemoveRequest) Validate() error { return nil } +// AffinityLabelRemove clear affinity label for compute func (c Compute) AffinityLabelRemove(ctx context.Context, req AffinityLabelRemoveRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/affinity_label_set.go b/pkg/cloudapi/compute/affinity_label_set.go index b1bfab4..6ec4b2e 100644 --- a/pkg/cloudapi/compute/affinity_label_set.go +++ b/pkg/cloudapi/compute/affinity_label_set.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for set affinity label for compute type AffinityLabelSetRequest struct { - ComputeID uint64 `url:"computeId"` + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Affinity group label + // Required: true AffinityLabel string `url:"affinityLabel"` } -func (crq AffinityLabelSetRequest) Validate() error { +func (crq AffinityLabelSetRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -23,8 +29,9 @@ func (crq AffinityLabelSetRequest) Validate() error { return nil } +// AffinityLabelSet set affinity label for compute func (c Compute) AffinityLabelSet(ctx context.Context, req AffinityLabelSetRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/affinity_relations.go b/pkg/cloudapi/compute/affinity_relations.go index 2ad8731..5e1fba1 100644 --- a/pkg/cloudapi/compute/affinity_relations.go +++ b/pkg/cloudapi/compute/affinity_relations.go @@ -7,12 +7,14 @@ import ( "net/http" ) +// Request struct for get dict of computes type AffinityRelationsRequest struct { - ComputeID uint64 `url:"computeId"` - AffinityLabel string `url:"affinityLabel"` + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` } -func (crq AffinityRelationsRequest) Validate() error { +func (crq AffinityRelationsRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -20,8 +22,9 @@ func (crq AffinityRelationsRequest) Validate() error { return nil } -func (c Compute) AffinityRelations(ctx context.Context, req AffinityRelationsRequest) (*AffinityRelations, error) { - err := req.Validate() +// AffinityRelations gets dict of computes divided by affinity and anti affinity rules +func (c Compute) AffinityRelations(ctx context.Context, req AffinityRelationsRequest) (*RecordAffinityRelations, error) { + err := req.validate() if err != nil { return nil, err } @@ -33,12 +36,12 @@ func (c Compute) AffinityRelations(ctx context.Context, req AffinityRelationsReq return nil, err } - relations := &AffinityRelations{} + info := RecordAffinityRelations{} - err = json.Unmarshal(res, relations) + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return relations, nil + return &info, nil } diff --git a/pkg/cloudapi/compute/affinity_rule_add.go b/pkg/cloudapi/compute/affinity_rule_add.go index a1d52dd..9cd8b7d 100644 --- a/pkg/cloudapi/compute/affinity_rule_add.go +++ b/pkg/cloudapi/compute/affinity_rule_add.go @@ -9,50 +9,68 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for add affinity rule type AffinityRuleAddRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` - Topology string `url:"topology"` - Policy string `url:"policy"` - Mode string `url:"mode"` - Key string `url:"key"` - Value string `url:"value"` + + // Compute or node, for whom rule applies + // Required: true + Topology string `url:"topology"` + + // The degree of 'strictness' of this rule + // Should be one of: + // - RECOMMENDED + // - REQUIRED + // Required: true + Policy string `url:"policy"` + + // The comparison mode is 'value', recorded by the specified 'key' + // Should be one of: + // - EQ + // - EN + // - ANY + // Required: true + Mode string `url:"mode"` + + // Key that are taken into account when analyzing this rule will be identified + // Required: true + Key string `url:"key"` + + // Value that must match the key to be taken into account when analyzing this rule + // Required: true + Value string `url:"value"` } -func (crq AffinityRuleAddRequest) Validate() error { +func (crq AffinityRuleAddRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } if crq.Topology == "" { return errors.New("validation-error: field Topology can not be empty") } - validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"}) if !validator { return errors.New("validation-error: field Topology can be only compute or node") } - if crq.Policy == "" { return errors.New("validation-error: field Policy can not be empty") } - validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"}) if !validator { return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED") } - if crq.Mode == "" { return errors.New("validation-error: field Mode can not be empty") } - validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"}) if !validator { return errors.New("validation-error: field Mode can be only EQ, NE or ANY") } - if crq.Key == "" { return errors.New("validation-error: field Key can not be empty") } - if crq.Value == "" { return errors.New("validation-error: field Value can not be empty") } @@ -60,8 +78,9 @@ func (crq AffinityRuleAddRequest) Validate() error { return nil } +// AffinityRuleAdd add affinity rule func (c Compute) AffinityRuleAdd(ctx context.Context, req AffinityRuleAddRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/affinity_rule_remove.go b/pkg/cloudapi/compute/affinity_rule_remove.go index 37b4676..bfba83d 100644 --- a/pkg/cloudapi/compute/affinity_rule_remove.go +++ b/pkg/cloudapi/compute/affinity_rule_remove.go @@ -9,50 +9,68 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for remove affinity rule type AffinityRuleRemoveRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` - Topology string `url:"topology"` - Policy string `url:"policy"` - Mode string `url:"mode"` - Key string `url:"key"` - Value string `url:"value"` + + // Compute or node, for whom rule applies + // Required: true + Topology string `url:"topology"` + + // The degree of 'strictness' of this rule + // Should be one of: + // - RECOMMENDED + // - REQUIRED + // Required: true + Policy string `url:"policy"` + + // The comparison mode is 'value', recorded by the specified 'key' + // Should be one of: + // - EQ + // - EN + // - ANY + // Required: true + Mode string `url:"mode"` + + // Key that are taken into account when analyzing this rule will be identified + // Required: true + Key string `url:"key"` + + // Value that must match the key to be taken into account when analyzing this rule + // Required: true + Value string `url:"value"` } -func (crq AffinityRuleRemoveRequest) Validate() error { +func (crq AffinityRuleRemoveRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } if crq.Topology == "" { return errors.New("validation-error: field Topology can not be empty") } - validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"}) if !validator { return errors.New("validation-error: field Topology can be only compute or node") } - if crq.Policy == "" { return errors.New("validation-error: field Policy can not be empty") } - validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"}) if !validator { return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED") } - if crq.Mode == "" { return errors.New("validation-error: field Mode can not be empty") } - validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"}) if !validator { return errors.New("validation-error: field Mode can be only EQ, NE or ANY") } - if crq.Key == "" { return errors.New("validation-error: field Key can not be empty") } - if crq.Value == "" { return errors.New("validation-error: field Value can not be empty") } @@ -60,8 +78,9 @@ func (crq AffinityRuleRemoveRequest) Validate() error { return nil } +// AffinityRuleRemove remove affinity rule func (c Compute) AffinityRuleRemove(ctx context.Context, req AffinityRuleRemoveRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/affinity_rules_clear.go b/pkg/cloudapi/compute/affinity_rules_clear.go index 4ed565f..2f33efc 100644 --- a/pkg/cloudapi/compute/affinity_rules_clear.go +++ b/pkg/cloudapi/compute/affinity_rules_clear.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for clear affinity rules type AffinityRulesClearRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq AffinityRulesClearRequest) Validate() error { +func (crq AffinityRulesClearRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq AffinityRulesClearRequest) Validate() error { return nil } +// AffinityRulesClear clear affinity rules func (c Compute) AffinityRulesClear(ctx context.Context, req AffinityRulesClearRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/anti_affinity_rule_add.go b/pkg/cloudapi/compute/anti_affinity_rule_add.go index 366ab45..7e90088 100644 --- a/pkg/cloudapi/compute/anti_affinity_rule_add.go +++ b/pkg/cloudapi/compute/anti_affinity_rule_add.go @@ -9,50 +9,68 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for add anti affinity rule type AntiAffinityRuleAddRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` - Topology string `url:"topology"` - Policy string `url:"policy"` - Mode string `url:"mode"` - Key string `url:"key"` - Value string `url:"value"` + + // Compute or node, for whom rule applies + // Required: true + Topology string `url:"topology"` + + // The degree of 'strictness' of this rule + // Should be one of: + // - RECOMMENDED + // - REQUIRED + // Required: true + Policy string `url:"policy"` + + // The comparison mode is 'value', recorded by the specified 'key' + // Should be one of: + // - EQ + // - EN + // - ANY + // Required: true + Mode string `url:"mode"` + + // Key that are taken into account when analyzing this rule will be identified + // Required: true + Key string `url:"key"` + + // Value that must match the key to be taken into account when analyzing this rule + // Required: true + Value string `url:"value"` } -func (crq AntiAffinityRuleAddRequest) Validate() error { +func (crq AntiAffinityRuleAddRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } if crq.Topology == "" { return errors.New("validation-error: field Topology can not be empty") } - validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"}) if !validator { return errors.New("validation-error: field Topology can be only compute or node") } - if crq.Policy == "" { return errors.New("validation-error: field Policy can not be empty") } - validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"}) if !validator { return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED") } - if crq.Mode == "" { return errors.New("validation-error: field Mode can not be empty") } - validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"}) if !validator { return errors.New("validation-error: field Mode can be only EQ, NE or ANY") } - if crq.Key == "" { return errors.New("validation-error: field Key can not be empty") } - if crq.Value == "" { return errors.New("validation-error: field Value can not be empty") } @@ -60,8 +78,9 @@ func (crq AntiAffinityRuleAddRequest) Validate() error { return nil } +// AntiAffinityRuleAdd add anti affinity rule func (c Compute) AntiAffinityRuleAdd(ctx context.Context, req AntiAffinityRuleAddRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/anti_affinity_rule_remove.go b/pkg/cloudapi/compute/anti_affinity_rule_remove.go index 031334d..45ac7a5 100644 --- a/pkg/cloudapi/compute/anti_affinity_rule_remove.go +++ b/pkg/cloudapi/compute/anti_affinity_rule_remove.go @@ -9,50 +9,68 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for remove anti affinity rule type AntiAffinityRuleRemoveRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` - Topology string `url:"topology"` - Policy string `url:"policy"` - Mode string `url:"mode"` - Key string `url:"key"` - Value string `url:"value"` + + // Compute or node, for whom rule applies + // Required: true + Topology string `url:"topology"` + + // The degree of 'strictness' of this rule + // Should be one of: + // - RECOMMENDED + // - REQUIRED + // Required: true + Policy string `url:"policy"` + + // The comparison mode is 'value', recorded by the specified 'key' + // Should be one of: + // - EQ + // - EN + // - ANY + // Required: true + Mode string `url:"mode"` + + // Key that are taken into account when analyzing this rule will be identified + // Required: true + Key string `url:"key"` + + // Value that must match the key to be taken into account when analyzing this rule + // Required: true + Value string `url:"value"` } -func (crq AntiAffinityRuleRemoveRequest) Validate() error { +func (crq AntiAffinityRuleRemoveRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } if crq.Topology == "" { return errors.New("validation-error: field Topology can not be empty") } - validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"}) if !validator { return errors.New("validation-error: field Topology can be only compute or node") } - if crq.Policy == "" { return errors.New("validation-error: field Policy can not be empty") } - validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"}) if !validator { return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED") } - if crq.Mode == "" { return errors.New("validation-error: field Mode can not be empty") } - validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"}) if !validator { return errors.New("validation-error: field Mode can be only EQ, NE or ANY") } - if crq.Key == "" { return errors.New("validation-error: field Key can not be empty") } - if crq.Value == "" { return errors.New("validation-error: field Value can not be empty") } @@ -60,8 +78,9 @@ func (crq AntiAffinityRuleRemoveRequest) Validate() error { return nil } +// AntiAffinityRuleRemove remove anti affinity rule func (c Compute) AntiAffinityRuleRemove(ctx context.Context, req AntiAffinityRuleRemoveRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/anti_affinity_rules_clear.go b/pkg/cloudapi/compute/anti_affinity_rules_clear.go index ac58234..b495b33 100644 --- a/pkg/cloudapi/compute/anti_affinity_rules_clear.go +++ b/pkg/cloudapi/compute/anti_affinity_rules_clear.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for clear anti affinity rules type AntiAffinityRulesClearRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq AntiAffinityRulesClearRequest) Validate() error { +func (crq AntiAffinityRulesClearRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq AntiAffinityRulesClearRequest) Validate() error { return nil } +// AntiAffinityRulesClear clear anti affinity rules func (c Compute) AntiAffinityRulesClear(ctx context.Context, req AntiAffinityRulesClearRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/attach_gpu.go b/pkg/cloudapi/compute/attach_gpu.go index 634d131..36c7ec1 100644 --- a/pkg/cloudapi/compute/attach_gpu.go +++ b/pkg/cloudapi/compute/attach_gpu.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for attach GPU for compute type AttachGPURequest struct { + // Identifier compute + // Required: true ComputeID uint64 `url:"computeId"` - VGPUID uint64 `url:"vgpuId"` + + // Identifier vGPU + // Required: true + VGPUID uint64 `url:"vgpuId"` } -func (crq AttachGPURequest) Validate() error { +func (crq AttachGPURequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } - if crq.VGPUID == 0 { return errors.New("validation-error: field VGPUID can not be empty or equal to 0") } @@ -24,8 +29,9 @@ func (crq AttachGPURequest) Validate() error { return nil } +// AttachGPU attach GPU for compute, returns vgpu id on success func (c Compute) AttachGPU(ctx context.Context, req AttachGPURequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } diff --git a/pkg/cloudapi/compute/attach_pci_device.go b/pkg/cloudapi/compute/attach_pci_device.go index 58f2630..bf9ae23 100644 --- a/pkg/cloudapi/compute/attach_pci_device.go +++ b/pkg/cloudapi/compute/attach_pci_device.go @@ -7,16 +7,21 @@ import ( "strconv" ) -type AttachPciDeviceRequest struct { +// Request struct for atttach PCI device +type AttachPCIDeviceRequest struct { + // Identifier compute + // Required: true ComputeID uint64 `url:"computeId"` - DeviceID uint64 `url:"deviceId"` + + // PCI device ID + // Required: true + DeviceID uint64 `url:"deviceId"` } -func (crq AttachPciDeviceRequest) Validate() error { +func (crq AttachPCIDeviceRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } - if crq.DeviceID == 0 { return errors.New("validation-error: field DeviceID can not be empty or equal to 0") } @@ -24,8 +29,9 @@ func (crq AttachPciDeviceRequest) Validate() error { return nil } -func (c Compute) AttachPciDevice(ctx context.Context, req AttachPciDeviceRequest) (bool, error) { - err := req.Validate() +// AttachPCIDevice attach PCI device +func (c Compute) AttachPCIDevice(ctx context.Context, req AttachPCIDeviceRequest) (bool, error) { + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/audits.go b/pkg/cloudapi/compute/audits.go index e4b9d0e..1087b15 100644 --- a/pkg/cloudapi/compute/audits.go +++ b/pkg/cloudapi/compute/audits.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get audit records type AuditsRequest struct { + // ID of the compute + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq AuditsRequest) Validate() error { +func (crq AuditsRequest) validate() error { if crq.ComputeID == 0 { return errors.New("field ComputeID can not be empty or equal to 0") } @@ -19,21 +22,26 @@ func (crq AuditsRequest) Validate() error { return nil } -func (c Compute) Audits(ctx context.Context, req AuditsRequest) (AuditList, error) { - if err := req.Validate(); err != nil { +// Audits gets audit records for the specified compute object +func (c Compute) Audits(ctx context.Context, req AuditsRequest) (ListAudits, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/compute/audits" - auditListRaw, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - auditList := AuditList{} - if err := json.Unmarshal(auditListRaw, &auditList); err != nil { + list := ListAudits{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return auditList, nil + return list, nil } diff --git a/pkg/cloudapi/compute/cd_eject.go b/pkg/cloudapi/compute/cd_eject.go index 3c8e7db..212ef1e 100644 --- a/pkg/cloudapi/compute/cd_eject.go +++ b/pkg/cloudapi/compute/cd_eject.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for eject CD image type CDEjectRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq CDEjectRequest) Validate() error { +func (crq CDEjectRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq CDEjectRequest) Validate() error { return nil } +// CDEject eject CD image to compute's CD-ROM func (c Compute) CDEject(ctx context.Context, req CDEjectRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/cd_insert.go b/pkg/cloudapi/compute/cd_insert.go index 3eaf174..30a9bf9 100644 --- a/pkg/cloudapi/compute/cd_insert.go +++ b/pkg/cloudapi/compute/cd_insert.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for insert new CD image type CDInsertRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` - CDROMID uint64 `url:"cdromId"` + + // ID of CD-ROM image + // Required: true + CDROMID uint64 `url:"cdromId"` } -func (crq CDInsertRequest) Validate() error { +func (crq CDInsertRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -23,8 +29,9 @@ func (crq CDInsertRequest) Validate() error { return nil } +// CDInsert insert new CD image to compute's CD-ROM func (c Compute) CDInsert(ctx context.Context, req CDInsertRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/clone.go b/pkg/cloudapi/compute/clone.go index 6e84a31..e113c7a 100644 --- a/pkg/cloudapi/compute/clone.go +++ b/pkg/cloudapi/compute/clone.go @@ -7,14 +7,26 @@ import ( "strconv" ) +// Request struct for clone compute instance type CloneRequest struct { - ComputeID uint64 `url:"computeId"` - Name string `url:"name"` + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Name of the clone + // Required: true + Name string `url:"name"` + + // Timestamp of the parent's snapshot to create clone from + // Required: false SnapshotTimestamp uint64 `url:"snapshotTimestamp"` - SnapshotName string `url:"snapshotName"` + + // Name of the parent's snapshot to create clone from + // Required: false + SnapshotName string `url:"snapshotName"` } -func (crq CloneRequest) Validate() error { +func (crq CloneRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -25,8 +37,9 @@ func (crq CloneRequest) Validate() error { return nil } +// Clone clones compute instance func (c Compute) Clone(ctx context.Context, req CloneRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } @@ -42,5 +55,6 @@ func (c Compute) Clone(ctx context.Context, req CloneRequest) (uint64, error) { if err != nil { return 0, err } + return result, nil } diff --git a/pkg/cloudapi/compute/compute.go b/pkg/cloudapi/compute/compute.go index 4ebedce..17974ad 100644 --- a/pkg/cloudapi/compute/compute.go +++ b/pkg/cloudapi/compute/compute.go @@ -1,13 +1,16 @@ +// API Actor for managing Compute. This actor is a final API for endusers to manage Compute package compute import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to compute type Compute struct { client interfaces.Caller } +// Builder for compute endpoints func New(client interfaces.Caller) *Compute { return &Compute{ client, diff --git a/pkg/cloudapi/compute/create_template.go b/pkg/cloudapi/compute/create_template.go index 49b39ec..5a6e437 100644 --- a/pkg/cloudapi/compute/create_template.go +++ b/pkg/cloudapi/compute/create_template.go @@ -8,17 +8,27 @@ import ( "strings" ) +// Request struct for create template type CreateTemplateRequest struct { + // ID of the compute to create template from + // Required: true ComputeID uint64 `url:"computeId"` - Name string `url:"name"` - Async bool `url:"async"` + + // Name to assign to the template being created + // Required: true + Name string `url:"name"` + + // Async API call + // For async call use CreateTemplateAsync + // For sync call use CreateTemplate + // Required: true + async bool `url:"async"` } -func (crq CreateTemplateRequest) Validate() error { +func (crq CreateTemplateRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } - if crq.Name == "" { return errors.New("validation-error: field Name can not be empty") } @@ -26,13 +36,14 @@ func (crq CreateTemplateRequest) Validate() error { return nil } +// CreateTemplate create template from compute instance func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } - req.Async = false + req.async = false url := "/cloudapi/compute/createTemplate" @@ -49,13 +60,14 @@ func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest) return result, nil } +// CreateTemplateAsync create template from compute instance func (c Compute) CreateTemplateAsync(ctx context.Context, req CreateTemplateRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } - req.Async = true + req.async = true url := "/cloudapi/compute/createTemplate" diff --git a/pkg/cloudapi/compute/delete.go b/pkg/cloudapi/compute/delete.go index c17fd1a..47d1452 100644 --- a/pkg/cloudapi/compute/delete.go +++ b/pkg/cloudapi/compute/delete.go @@ -7,13 +7,22 @@ import ( "strconv" ) +// Request struct for delete compute type DeleteRequest struct { - ComputeID uint64 `url:"computeId"` - Permanently bool `url:"permanently,omitempty"` - DetachDisks bool `url:"detachDisks,omitempty"` + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Delete permanently + // Required: false + Permanently bool `url:"permanently,omitempty"` + + // Set True if you want to detach data disks (if any) from the compute before its deletion + // Required: false + DetachDisks bool `url:"detachDisks,omitempty"` } -func (crq DeleteRequest) Validate() error { +func (crq DeleteRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -21,8 +30,9 @@ func (crq DeleteRequest) Validate() error { return nil } +// Delete deletes compute func (c Compute) Delete(ctx context.Context, req DeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -38,5 +48,6 @@ func (c Compute) Delete(ctx context.Context, req DeleteRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/detach_gpu.go b/pkg/cloudapi/compute/detach_gpu.go index 6b69381..79c973e 100644 --- a/pkg/cloudapi/compute/detach_gpu.go +++ b/pkg/cloudapi/compute/detach_gpu.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for detach vgpu for compute type DetachGPURequest struct { + // Identifier compute + // Required: true ComputeID uint64 `url:"computeId"` - VGPUID int64 `url:"vgpuId,omitempty"` + + // Identifier virtual GPU + // Required: false + VGPUID int64 `url:"vgpuId,omitempty"` } -func (crq DetachGPURequest) Validate() error { +func (crq DetachGPURequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -20,8 +26,10 @@ func (crq DetachGPURequest) Validate() error { return nil } +// DetachGPU detach vgpu for compute. +// If param vgpuid is equivalent -1, then detach all vgpu for compute func (c Compute) DetachGPU(ctx context.Context, req DetachGPURequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/detach_pci_device.go b/pkg/cloudapi/compute/detach_pci_device.go index 8ecc361..5e3322e 100644 --- a/pkg/cloudapi/compute/detach_pci_device.go +++ b/pkg/cloudapi/compute/detach_pci_device.go @@ -7,16 +7,21 @@ import ( "strconv" ) -type DetachPciDeviceRequest struct { +// Request struct for detach PCI device +type DetachPCIDeviceRequest struct { + // Identifier compute + // Required: true ComputeID uint64 `url:"computeId"` - DeviceID uint64 `url:"deviceId"` + + // Pci device ID + // Required: true + DeviceID uint64 `url:"deviceId"` } -func (crq DetachPciDeviceRequest) Validate() error { +func (crq DetachPCIDeviceRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } - if crq.DeviceID == 0 { return errors.New("validation-error: field DeviceID can not be empty or equal to 0") } @@ -24,8 +29,9 @@ func (crq DetachPciDeviceRequest) Validate() error { return nil } -func (c Compute) DetachPciDevice(ctx context.Context, req DetachPciDeviceRequest) (bool, error) { - err := req.Validate() +// DetachPCIDevice detach PCI device +func (c Compute) DetachPCIDevice(ctx context.Context, req DetachPCIDeviceRequest) (bool, error) { + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/disable.go b/pkg/cloudapi/compute/disable.go index 014104b..75bc25b 100644 --- a/pkg/cloudapi/compute/disable.go +++ b/pkg/cloudapi/compute/disable.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for disable compute type DisableRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq DisableRequest) Validate() error { +func (crq DisableRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq DisableRequest) Validate() error { return nil } +// Disable disables compute func (c Compute) Disable(ctx context.Context, req DisableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/disk_add.go b/pkg/cloudapi/compute/disk_add.go index 8a01fa8..91457e8 100644 --- a/pkg/cloudapi/compute/disk_add.go +++ b/pkg/cloudapi/compute/disk_add.go @@ -7,26 +7,53 @@ import ( "strconv" ) +// Request struct for create and attach disk to compute type DiskAddRequest struct { - ComputeID uint64 `url:"computeId"` - DiskName string `url:"diskName"` - Size uint64 `url:"size"` - DiskType string `url:"diskType,omitempty"` - SepID uint64 `url:"sepId,omitempty"` - Pool string `url:"pool,omitempty"` + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Name for disk + // Required: true + DiskName string `url:"diskName"` + + // Disk size in GB + // Required: true + Size uint64 `url:"size"` + + // Type of the disk + // Should be one of: + // - D + // - B + // Required: false + DiskType string `url:"diskType,omitempty"` + + // Storage endpoint provider ID + // By default the same with boot disk + // Required: false + SepID uint64 `url:"sepId,omitempty"` + + // Pool name + // By default will be chosen automatically + // Required: false + Pool string `url:"pool,omitempty"` + + // Optional description + // Required: false Description string `url:"desc,omitempty"` - ImageID uint64 `url:"imageId,omitempty"` + + // Specify image id for create disk from template + // Required: false + ImageID uint64 `url:"imageId,omitempty"` } -func (crq DiskAddRequest) Validate() error { +func (crq DiskAddRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } - if crq.Size == 0 { return errors.New("validation-error: field Size can not be empty or equal to 0") } - if crq.DiskName == "" { return errors.New("validation-error: field DiskName can not be empty or equal to 0") } @@ -34,8 +61,9 @@ func (crq DiskAddRequest) Validate() error { return nil } +// DiskAdd creates new disk and attach to compute func (c Compute) DiskAdd(ctx context.Context, req DiskAddRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } diff --git a/pkg/cloudapi/compute/disk_attach.go b/pkg/cloudapi/compute/disk_attach.go index ee93e1c..68d1eeb 100644 --- a/pkg/cloudapi/compute/disk_attach.go +++ b/pkg/cloudapi/compute/disk_attach.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for attach disk to compute type DiskAttachRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` - DiskID uint64 `url:"diskId"` + + // ID of the disk to attach + // Required: true + DiskID uint64 `url:"diskId"` } -func (crq DiskAttachRequest) Validate() error { +func (crq DiskAttachRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } - if crq.DiskID == 0 { return errors.New("validation-error: field DiskID can not be empty or equal to 0") } @@ -24,8 +29,9 @@ func (crq DiskAttachRequest) Validate() error { return nil } +// DiskAttach attach disk to compute func (c Compute) DiskAttach(ctx context.Context, req DiskAttachRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/disk_del.go b/pkg/cloudapi/compute/disk_del.go index cf8f7bb..586b369 100644 --- a/pkg/cloudapi/compute/disk_del.go +++ b/pkg/cloudapi/compute/disk_del.go @@ -7,17 +7,25 @@ import ( "strconv" ) +// Request struct for detach and delete disk from compute type DiskDelRequest struct { - ComputeID uint64 `url:"computeId"` - DiskID uint64 `url:"diskId"` - Permanently bool `url:"permanently"` + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // ID of disk instance + // Required: true + DiskID uint64 `url:"diskId"` + + // False if disk is to be deleted to recycle bin + // Required: true + Permanently bool `url:"permanently"` } -func (crq DiskDelRequest) Validate() error { +func (crq DiskDelRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } - if crq.DiskID == 0 { return errors.New("validation-error: field DiskID can not be empty or equal to 0") } @@ -25,8 +33,9 @@ func (crq DiskDelRequest) Validate() error { return nil } +// DiskDel delete disk and detach from compute func (c Compute) DiskDel(ctx context.Context, req DiskDelRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/disk_detach.go b/pkg/cloudapi/compute/disk_detach.go index 1d699ea..0abc99f 100644 --- a/pkg/cloudapi/compute/disk_detach.go +++ b/pkg/cloudapi/compute/disk_detach.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for detach disk from compute type DiskDetachRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` - DiskID uint64 `url:"diskId"` + + // ID of the disk to detach + // Required: true + DiskID uint64 `url:"diskId"` } -func (crq DiskDetachRequest) Validate() error { +func (crq DiskDetachRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } - if crq.DiskID == 0 { return errors.New("validation-error: field DiskID can not be empty or equal to 0") } @@ -24,8 +29,9 @@ func (crq DiskDetachRequest) Validate() error { return nil } +// DiskDetach detach disk from compute func (c Compute) DiskDetach(ctx context.Context, req DiskDetachRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/disk_qos.go b/pkg/cloudapi/compute/disk_qos.go index b23457f..fc1a7e0 100644 --- a/pkg/cloudapi/compute/disk_qos.go +++ b/pkg/cloudapi/compute/disk_qos.go @@ -7,21 +7,28 @@ import ( "strconv" ) +// Request struct for change QoS of the disk type DiskQOSRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` - DiskID uint64 `url:"diskId"` - Limits string `url:"limits"` + + // ID of the disk to apply limits + // Required: true + DiskID uint64 `url:"diskId"` + + // Limit IO for a certain disk total and read/write options are not allowed to be combined + // Required: true + Limits string `url:"limits"` } -func (crq DiskQOSRequest) Validate() error { +func (crq DiskQOSRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } - if crq.DiskID == 0 { return errors.New("validation-error: field DiskID can not be empty or equal to 0") } - if crq.Limits == "" { return errors.New("validation-error: field Limits can not be empty") } @@ -29,8 +36,9 @@ func (crq DiskQOSRequest) Validate() error { return nil } +// DiskQOS change QoS of the disk func (c Compute) DiskQOS(ctx context.Context, req DiskQOSRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/disk_resize.go b/pkg/cloudapi/compute/disk_resize.go index ca06a77..33bf49a 100644 --- a/pkg/cloudapi/compute/disk_resize.go +++ b/pkg/cloudapi/compute/disk_resize.go @@ -7,21 +7,28 @@ import ( "strconv" ) +// Request struct for change disk size type DiskResizeRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` - DiskID uint64 `url:"diskId"` - Size uint64 `url:"size"` + + // ID of the disk to resize + // Required: true + DiskID uint64 `url:"diskId"` + + // New disk size + // Required: true + Size uint64 `url:"size"` } -func (crq DiskResizeRequest) Validate() error { +func (crq DiskResizeRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } - if crq.DiskID == 0 { return errors.New("validation-error: field DiskID can not be empty or equal to 0") } - if crq.Size == 0 { return errors.New("validation-error: field Size can not be empty or equal to 0") } @@ -29,8 +36,9 @@ func (crq DiskResizeRequest) Validate() error { return nil } +// DiskResize change disk size func (c Compute) DiskResize(ctx context.Context, req DiskResizeRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/enable.go b/pkg/cloudapi/compute/enable.go index df7dd18..5aa14f8 100644 --- a/pkg/cloudapi/compute/enable.go +++ b/pkg/cloudapi/compute/enable.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for enable compute type EnableRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq EnableRequest) Validate() error { +func (crq EnableRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq EnableRequest) Validate() error { return nil } +// Enable enables compute func (c Compute) Enable(ctx context.Context, req EnableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/get.go b/pkg/cloudapi/compute/get.go index dab033e..fd70b86 100644 --- a/pkg/cloudapi/compute/get.go +++ b/pkg/cloudapi/compute/get.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request for get information about compute type GetRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq GetRequest) Validate() error { +func (crq GetRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq GetRequest) Validate() error { return nil } -func (c Compute) Get(ctx context.Context, req GetRequest) (*ComputeRecord, error) { - err := req.Validate() +// Get Gets information about compute +func (c Compute) Get(ctx context.Context, req GetRequest) (*RecordCompute, error) { + err := req.validate() if err != nil { return nil, err } @@ -32,11 +36,12 @@ func (c Compute) Get(ctx context.Context, req GetRequest) (*ComputeRecord, error return nil, err } - compute := &ComputeRecord{} - err = json.Unmarshal(res, compute) + info := RecordCompute{} + + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return compute, nil + return &info, nil } diff --git a/pkg/cloudapi/compute/get_audits.go b/pkg/cloudapi/compute/get_audits.go index 18a4460..849472d 100644 --- a/pkg/cloudapi/compute/get_audits.go +++ b/pkg/cloudapi/compute/get_audits.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get compute audits type GetAuditsRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq GetAuditsRequest) Validate() error { +func (crq GetAuditsRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq GetAuditsRequest) Validate() error { return nil } -func (c Compute) GetAudits(ctx context.Context, req GetAuditsRequest) (AuditShortList, error) { - err := req.Validate() +// GetAudits gets compute audits +func (c Compute) GetAudits(ctx context.Context, req GetAuditsRequest) (ListShortAudits, error) { + err := req.validate() if err != nil { return nil, err } @@ -32,11 +36,12 @@ func (c Compute) GetAudits(ctx context.Context, req GetAuditsRequest) (AuditShor return nil, err } - auditsList := AuditShortList{} - err = json.Unmarshal(res, &auditsList) + list := ListShortAudits{} + + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return auditsList, nil + return list, nil } diff --git a/pkg/cloudapi/compute/get_console_url.go b/pkg/cloudapi/compute/get_console_url.go index bc4d98f..31c340f 100644 --- a/pkg/cloudapi/compute/get_console_url.go +++ b/pkg/cloudapi/compute/get_console_url.go @@ -7,11 +7,14 @@ import ( "strings" ) +// Request struct for get console URL type GetConsoleURLRequest struct { + // ID of compute instance to get console for + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq GetConsoleURLRequest) Validate() error { +func (crq GetConsoleURLRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq GetConsoleURLRequest) Validate() error { return nil } +// GetConsoleURL gets computes console URL func (c Compute) GetConsoleURL(ctx context.Context, req GetConsoleURLRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } diff --git a/pkg/cloudapi/compute/get_log.go b/pkg/cloudapi/compute/get_log.go index 9699063..0df1b89 100644 --- a/pkg/cloudapi/compute/get_log.go +++ b/pkg/cloudapi/compute/get_log.go @@ -6,16 +6,21 @@ import ( "net/http" ) +// Request struct for get compute logs type GetLogRequest struct { + // ID of compute instance to get log for + // Required: true ComputeID uint64 `url:"computeId"` - Path string `url:"path"` + + // Path to log file + // Required: true + Path string `url:"path"` } -func (crq GetLogRequest) Validate() error { +func (crq GetLogRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } - if crq.Path == "" { return errors.New("validation-error: field Path can not be empty") } @@ -23,8 +28,9 @@ func (crq GetLogRequest) Validate() error { return nil } +// GetLog gets compute's log file by path func (c Compute) GetLog(ctx context.Context, req GetLogRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } @@ -39,16 +45,15 @@ func (c Compute) GetLog(ctx context.Context, req GetLogRequest) (string, error) return string(res), nil } +// GetLogGet gets compute's log file by path func (c Compute) GetLogGet(ctx context.Context, req GetLogRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } - url := "/compute/getLog" - prefix := "/cloudapi" + url := "/cloudapi//compute/getLog" - url = prefix + url res, err := c.client.DecortApiCall(ctx, http.MethodGet, url, req) if err != nil { return "", err diff --git a/pkg/cloudapi/compute/list.go b/pkg/cloudapi/compute/list.go index bbd22a6..1d55179 100644 --- a/pkg/cloudapi/compute/list.go +++ b/pkg/cloudapi/compute/list.go @@ -6,14 +6,24 @@ import ( "net/http" ) +// Request struct for get list available computes type ListRequest struct { - IncludeDeleted bool `url:"includedeleted,omitempty"` - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` -} + // Include deleted computes + // Required: false + IncludeDeleted bool `url:"includedeleted,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` -func (c Compute) List(ctx context.Context, req ListRequest) (ComputeList, error) { + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} +// List gets list of the available computes. +// Filtering based on status is possible +func (c Compute) List(ctx context.Context, req ListRequest) (ListComputes, error) { url := "/cloudapi/compute/list" res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) @@ -21,12 +31,12 @@ func (c Compute) List(ctx context.Context, req ListRequest) (ComputeList, error) return nil, err } - computeList := ComputeList{} + list := ListComputes{} - err = json.Unmarshal(res, &computeList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return computeList, nil + return list, nil } diff --git a/pkg/cloudapi/compute/list_deleted.go b/pkg/cloudapi/compute/list_deleted.go index c327921..d94f706 100644 --- a/pkg/cloudapi/compute/list_deleted.go +++ b/pkg/cloudapi/compute/list_deleted.go @@ -6,13 +6,19 @@ import ( "net/http" ) +// Request struct for get deleted computes list type ListDeletedRequest struct { + // Page number + // Required: false Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false Size uint64 `url:"size,omitempty"` } -func (c Compute) ListDeleted(ctx context.Context, req ListDeletedRequest) (ComputeList, error) { - +// ListDeleted gets list all deleted computes +func (c Compute) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListComputes, error) { url := "/cloudapi/compute/listDeleted" res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) @@ -20,12 +26,12 @@ func (c Compute) ListDeleted(ctx context.Context, req ListDeletedRequest) (Compu return nil, err } - computeList := ComputeList{} + list := ListComputes{} - err = json.Unmarshal(res, &computeList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return computeList, nil + return list, nil } diff --git a/pkg/cloudapi/compute/list_pci_device.go b/pkg/cloudapi/compute/list_pci_device.go index fb0f097..6398666 100644 --- a/pkg/cloudapi/compute/list_pci_device.go +++ b/pkg/cloudapi/compute/list_pci_device.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list PCI devices type ListPCIDeviceRequest struct { + // Identifier compute + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq ListPCIDeviceRequest) Validate() error { +func (crq ListPCIDeviceRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq ListPCIDeviceRequest) Validate() error { return nil } +// ListPCIDevice gets list PCI device func (c Compute) ListPCIDevice(ctx context.Context, req ListPCIDeviceRequest) ([]interface{}, error) { - err := req.Validate() + err := req.validate() if err != nil { return nil, err } @@ -32,12 +36,12 @@ func (c Compute) ListPCIDevice(ctx context.Context, req ListPCIDeviceRequest) ([ return nil, err } - pciDeviceList := []interface{}{} + list := []interface{}{} - err = json.Unmarshal(res, &pciDeviceList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return pciDeviceList, nil + return list, nil } diff --git a/pkg/cloudapi/compute/list_vgpu.go b/pkg/cloudapi/compute/list_vgpu.go index dbbe0a0..c1bad07 100644 --- a/pkg/cloudapi/compute/list_vgpu.go +++ b/pkg/cloudapi/compute/list_vgpu.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list vGPU type ListVGPURequest struct { + // Identifier compute + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq ListVGPURequest) Validate() error { +func (crq ListVGPURequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq ListVGPURequest) Validate() error { return nil } +// ListVGPU gets list vGPU func (c Compute) ListVGPU(ctx context.Context, req ListVGPURequest) ([]interface{}, error) { - err := req.Validate() + err := req.validate() if err != nil { return nil, err } @@ -32,12 +36,12 @@ func (c Compute) ListVGPU(ctx context.Context, req ListVGPURequest) ([]interface return nil, err } - pciDeviceList := []interface{}{} + list := []interface{}{} - err = json.Unmarshal(res, &pciDeviceList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return pciDeviceList, nil + return list, nil } diff --git a/pkg/cloudapi/compute/models.go b/pkg/cloudapi/compute/models.go index e5fba38..fc62765 100644 --- a/pkg/cloudapi/compute/models.go +++ b/pkg/cloudapi/compute/models.go @@ -1,210 +1,510 @@ package compute -// ACL for compute -type UserList struct { - AccountACL ACLList `json:"accountACL"` - ComputeACL ACLList `json:"computeACL"` - RGACL ACLList `json:"rgACL"` +// Access Control List +type RecordACL struct { + // Account ACL list + AccountACL ListACL `json:"accountACL"` + + // Compute ACL list + ComputeACL ListACL `json:"computeACL"` + + // Resource group ACL list + RGACL ListACL `json:"rgACL"` } -type ACL struct { - Explicit bool `json:"explicit"` - GUID string `json:"guid"` - Right string `json:"right"` - Status string `json:"status"` - Type string `json:"type"` +// ACL information +type ItemACL struct { + // Explicit + Explicit bool `json:"explicit"` + + // GUID + GUID string `json:"guid"` + + // Right + Right string `json:"right"` + + // Status + Status string `json:"status"` + + // Type + Type string `json:"type"` + + // User group ID UserGroupID string `json:"userGroupId"` } -type ACLList []ACL +// List ACL +type ListACL []ItemACL + +// Main information about usage snapshot +type ItemUsageSnapshot struct { + // Count + Count uint64 `json:"count,omitempty"` -type SnapshotUsage struct { - Count uint64 `json:"count,omitempty"` - Stored float64 `json:"stored"` - Label string `json:"label,omitempty"` - Timestamp uint64 `json:"timestamp,omitempty"` + // Stored + Stored float64 `json:"stored"` + + // Label + Label string `json:"label,omitempty"` + + // Timestamp + Timestamp uint64 `json:"timestamp,omitempty"` } -type SnapshotUsageList []SnapshotUsage +// List of usage snapshot +type ListUsageSnapshots []ItemUsageSnapshot + +// Main information about snapshot +type ItemSnapshot struct { + // List disk ID + Disks []uint64 `json:"disks"` + + // GUID + GUID string `json:"guid"` -type Snapshot struct { - Disks []uint64 `json:"disks"` - GUID string `json:"guid"` - Label string `json:"label"` - Timestamp uint64 `json:"timestamp"` + // Label + Label string `json:"label"` + + // Timestamp + Timestamp uint64 `json:"timestamp"` } -type SnapshotList []Snapshot +// List of snapshots +type ListSnapShots []ItemSnapshot + +// Main information about port forward +type ItemPFW struct { + // ID + ID uint64 `json:"id"` + + // Local IP + LocalIP string `json:"localIp"` + + // Local port + LocalPort uint64 `json:"localPort"` -type PFW struct { - ID uint64 `json:"id"` - LocalIP string `json:"localIp"` - LocalPort uint64 `json:"localPort"` - Protocol string `json:"protocol"` - PublicPortEnd uint64 `json:"publicPortEnd"` + // Protocol + Protocol string `json:"protocol"` + + // Public port end + PublicPortEnd uint64 `json:"publicPortEnd"` + + // Public port start PublicPortStart uint64 `json:"publicPortStart"` - VMID uint64 `json:"vmId"` + + // Virtuel machine ID + VMID uint64 `json:"vmId"` } -type PFWList []PFW +// List port forwards +type ListPFWs []ItemPFW + +// Main information about affinity relations +type RecordAffinityRelations struct { + // Other node + OtherNode []interface{} `json:"otherNode"` -type AffinityRelations struct { - OtherNode []interface{} `json:"otherNode"` - OtherNodeIndirect []interface{} `json:"otherNodeIndirect"` + // Other node indirect + OtherNodeIndirect []interface{} `json:"otherNodeIndirect"` + + // Other node indirect soft OtherNodeIndirectSoft []interface{} `json:"otherNodeIndirectSoft"` - OtherNodeSoft []interface{} `json:"otherNodeSoft"` - SameNode []interface{} `json:"sameNode"` - SameNodeSoft []interface{} `json:"sameNodeSoft"` + + // Other node soft + OtherNodeSoft []interface{} `json:"otherNodeSoft"` + + // Same node + SameNode []interface{} `json:"sameNode"` + + // Same node soft + SameNodeSoft []interface{} `json:"sameNodeSoft"` } -type NetAttach struct { - ConnID uint64 `json:"connId"` - ConnType string `json:"connType"` - DefGW string `json:"defGw"` - FlipGroupID uint64 `json:"flipgroupId"` - GUID string `json:"guid"` - IPAddress string `json:"ipAddress"` - ListenSSH bool `json:"listenSsh"` - MAC string `json:"mac"` - Name string `json:"name"` - NetID uint64 `json:"netId"` - NetMask uint64 `json:"netMask"` - NetType string `json:"netType"` - PCISlot uint64 `json:"pciSlot"` - QOS QOS `json:"qos"` - Target string `json:"target"` - Type string `json:"type"` - VNFS []uint64 `json:"vnfs"` +// Main information about attached network +type RecordNetAttach struct { + // Connection ID + ConnID uint64 `json:"connId"` + + // Connection type + ConnType string `json:"connType"` + + // Default GW + DefGW string `json:"defGw"` + + // FLIPGroup ID + FLIPGroupID uint64 `json:"flipgroupId"` + + // GUID + GUID string `json:"guid"` + + // IP address + IPAddress string `json:"ipAddress"` + + // Listen SSH + ListenSSH bool `json:"listenSsh"` + + // MAC + MAC string `json:"mac"` + + // Name + Name string `json:"name"` + + // Network ID + NetID uint64 `json:"netId"` + + // Network mask + NetMask uint64 `json:"netMask"` + + // Network type + NetType string `json:"netType"` + + // PCI slot + PCISlot uint64 `json:"pciSlot"` + + // QOS + QOS QOS `json:"qos"` + + // Target + Target string `json:"target"` + + // Type + Type string `json:"type"` + + // List VNF IDs + VNFs []uint64 `json:"vnfs"` } -type Audit struct { - Call string `json:"call"` +// Detailed information about audit +type ItemAudit struct { + // Call + Call string `json:"call"` + + // Response time ResponseTime float64 `json:"responsetime"` - StatusCode uint64 `json:"statuscode"` - Timestamp float64 `json:"timestamp"` - User string `json:"user"` + + // Status code + StatusCode uint64 `json:"statuscode"` + + // Timestamp + Timestamp float64 `json:"timestamp"` + + // User + User string `json:"user"` } -type AuditList []Audit +// List Detailed audits +type ListAudits []ItemAudit + +// Short information about audit +type ItemShortAudit struct { + // Epoch + Epoch float64 `json:"epoch"` -type AuditShort struct { - Epoch float64 `json:"epoch"` - Message string `json:"message"` + // Message + Message string `json:"message"` } -type AuditShortList []AuditShort +// List short audits +type ListShortAudits []ItemShortAudit + +// Main information about rule +type ItemRule struct { + // GUID + GUID string `json:"guid"` -type Rule struct { - GUID string `json:"guid"` - Key string `json:"key"` - Mode string `json:"mode"` - Policy string `json:"policy"` + // Key + Key string `json:"key"` + + // Mode + Mode string `json:"mode"` + + // Policy + Policy string `json:"policy"` + + // Topology Topology string `json:"topology"` - Value string `json:"value"` + + // Value + Value string `json:"value"` } -type RuleList []Rule - -type ComputeRecord struct { - ACL UserList `json:"ACL"` - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - AffinityLabel string `json:"affinityLabel"` - AffinityRules RuleList `json:"affinityRules"` - AffinityWeight uint64 `json:"affinityWeight"` - AntiAffinityRules RuleList `json:"antiAffinityRules"` - Architecture string `json:"arch"` - BootOrder []string `json:"bootOrder"` - BootDiskSize uint64 `json:"bootdiskSize"` - CloneReference uint64 `json:"cloneReference"` - Clones []uint64 `json:"clones"` - ComputeCIID uint64 `json:"computeciId"` - CPU uint64 `json:"cpus"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - CustomFields map[string]interface{} `json:"customFields"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - Description string `json:"desc"` - Devices interface{} `json:"devices"` - Disks ComputeDiskList `json:"disks"` - Driver string `json:"driver"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - ImageID uint64 `json:"imageId"` - ImageName string `json:"imageName"` - Intefaces IntefaceList `json:"interfaces"` - LockStatus string `json:"lockStatus"` - ManagerID uint64 `json:"managerId"` - ManagerType string `json:"managerType"` - MigrationJob uint64 `json:"migrationjob"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - NatableVINSID uint64 `json:"natableVinsId"` - NatableVINSIP string `json:"natableVinsIp"` - NatableVINSName string `json:"natableVinsName"` - NatableVINSNetwork string `json:"natableVinsNetwork"` - NatableVINSNetworkName string `json:"natableVinsNetworkName"` - OSUsers OSUserList `json:"osUsers"` - Pinned bool `json:"pinned"` - RAM uint64 `json:"ram"` - ReferenceID string `json:"referenceId"` - Registered bool `json:"registered"` - ResName string `json:"resName"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - SnapSets SnapSetList `json:"snapSets"` - StatelessSepID uint64 `json:"statelessSepId"` - StatelessSepType string `json:"statelessSepType"` - Status string `json:"status"` - Tags map[string]string `json:"tags"` - TechStatus string `json:"techStatus"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - UserManaged bool `json:"userManaged"` - Userdata interface{} `json:"userdata"` - VGPUs []uint64 `json:"vgpus"` - VirtualImageID uint64 `json:"virtualImageId"` - VirtualImageName string `json:"virtualImageName"` +// List rules +type ListRules []ItemRule + +// Detailed information about compute +type RecordCompute struct { + // Access Control List + ACL RecordACL `json:"ACL"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Affinity label + AffinityLabel string `json:"affinityLabel"` + + // List affinity rules + AffinityRules ListRules `json:"affinityRules"` + + // Affinity weight + AffinityWeight uint64 `json:"affinityWeight"` + + // List anti affinity rules + AntiAffinityRules ListRules `json:"antiAffinityRules"` + + // Architecture + Architecture string `json:"arch"` + + // Boot order + BootOrder []string `json:"bootOrder"` + + // Boot disk size + BootDiskSize uint64 `json:"bootdiskSize"` + + // Clone reference + CloneReference uint64 `json:"cloneReference"` + + // List clone IDs + Clones []uint64 `json:"clones"` + + // Compute CI ID + ComputeCIID uint64 `json:"computeciId"` + + // Number of cores + CPU uint64 `json:"cpus"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Custom fields + CustomFields map[string]interface{} `json:"customFields"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // Devices + Devices interface{} `json:"devices"` + + // List disks in compute + Disks ListComputeDisks `json:"disks"` + + // Driver + Driver string `json:"driver"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Image ID + ImageID uint64 `json:"imageId"` + + // Image name + ImageName string `json:"imageName"` + + // List interfaces + Interfaces ListInterfaces `json:"interfaces"` + + // Lock status + LockStatus string `json:"lockStatus"` + + // Manager ID + ManagerID uint64 `json:"managerId"` + + // Manager type + ManagerType string `json:"managerType"` + + // Migration job + MigrationJob uint64 `json:"migrationjob"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Natable VINS ID + NatableVINSID uint64 `json:"natableVinsId"` + + // Natable VINS IP + NatableVINSIP string `json:"natableVinsIp"` + + // Natable VINS Name + NatableVINSName string `json:"natableVinsName"` + + // Natable VINS network + NatableVINSNetwork string `json:"natableVinsNetwork"` + + // Natable VINS network name + NatableVINSNetworkName string `json:"natableVinsNetworkName"` + + // List OS Users + OSUsers ListOSUser `json:"osUsers"` + + // Pinned or not + Pinned bool `json:"pinned"` + + // Number of RAM + RAM uint64 `json:"ram"` + + // Reference ID + ReferenceID string `json:"referenceId"` + + // Registered or not + Registered bool `json:"registered"` + + // Resource name + ResName string `json:"resName"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // List snapsets + SnapSets ListSnapSets `json:"snapSets"` + + // Stateless SepID + StatelessSepID uint64 `json:"statelessSepId"` + + // Stateless SepType + StatelessSepType string `json:"statelessSepType"` + + // Status + Status string `json:"status"` + + // Tags + Tags map[string]string `json:"tags"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // User Managed or not + UserManaged bool `json:"userManaged"` + + // Userdata + Userdata interface{} `json:"userdata"` + + // vGPU IDs + VGPUs []uint64 `json:"vgpus"` + + // Virtual image ID + VirtualImageID uint64 `json:"virtualImageId"` + + // Virtual image name + VirtualImageName string `json:"virtualImageName"` } -type OSUser struct { - GUID string `json:"guid"` - Login string `json:"login"` +// Main information about OS user +type ItemOSUser struct { + // GUID + GUID string `json:"guid"` + + // Login + Login string `json:"login"` + + // Password Password string `json:"password"` - PubKey string `json:"pubkey"` + + // Public key + PubKey string `json:"pubkey"` } -type OSUserList []OSUser +// List OS users +type ListOSUser []ItemOSUser + +// Main information about snapsets +type ItemSnapSet struct { + // List disk IDs + Disks []uint64 `json:"disks"` -type SnapSet struct { - Disks []uint64 `json:"disks"` - GUID string `json:"guid"` - Label string `json:"label"` - Timestamp uint64 `json:"timestamp"` + // GUID + GUID string `json:"guid"` + + // Label + Label string `json:"label"` + + // Timestamp + Timestamp uint64 `json:"timestamp"` } -type SnapSetList []SnapSet - -type VNFInterface struct { - ConnID uint64 `json:"connId"` - ConnType string `json:"connType"` - DefGW string `json:"defGw"` - FlipGroupID uint64 `json:"flipgroupId"` - GUID string `json:"guid"` - IPAddress string `json:"ipAddress"` - ListenSSH bool `json:"listenSsh"` - MAC string `json:"mac"` - Name string `json:"name"` - NetID uint64 `json:"netId"` - NetMask uint64 `json:"netMask"` - NetType string `json:"netType"` - PCISlot uint64 `json:"pciSlot"` - QOS QOS `json:"qos"` - Target string `json:"target"` - Type string `json:"type"` - VNFS []uint64 `json:"vnfs"` +// List snapsets +type ListSnapSets []ItemSnapSet + +// Main information about VNF +type ItemVNFInterface struct { + // Connection ID + ConnID uint64 `json:"connId"` + + // Connection type + ConnType string `json:"connType"` + + // Default GW + DefGW string `json:"defGw"` + + // FLIPGroup ID + FLIPGroupID uint64 `json:"flipgroupId"` + + // GUID + GUID string `json:"guid"` + + // IP address + IPAddress string `json:"ipAddress"` + + // Listen SSH or not + ListenSSH bool `json:"listenSsh"` + + // MAC + MAC string `json:"mac"` + + // Name + Name string `json:"name"` + + // Network ID + NetID uint64 `json:"netId"` + + // Network mask + NetMask uint64 `json:"netMask"` + + // Network type + NetType string `json:"netType"` + + // PCI slot + PCISlot uint64 `json:"pciSlot"` + + // QOS + QOS QOS `json:"qos"` + + // Target + Target string `json:"target"` + + // Type + Type string `json:"type"` + + // List VNF IDs + VNFs []uint64 `json:"vnfs"` } type QOS struct { @@ -214,134 +514,362 @@ type QOS struct { InRate uint64 `json:"inRate"` } -type IntefaceList []VNFInterface - -type ComputeDiskList []ComputeDisk - -type ComputeDisk struct { - Ckey string `json:"_ckey"` - ACL map[string]interface{} `json:"acl"` - AccountID uint64 `json:"accountId"` - Bootpartition uint64 `json:"bootPartition"` - CreatedTime uint64 `json:"createdTime"` - DeletedTime uint64 `json:"deletedTime"` - Description string `json:"desc"` - DestructionTime uint64 `json:"destructionTime"` - DiskPath string `json:"diskPath"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - ImageID uint64 `json:"imageId"` - Images []uint64 `json:"images"` - IOTune IOTune `json:"iotune"` - IQN string `json:"iqn"` - Login string `json:"login"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - Order uint64 `json:"order"` - Params string `json:"params"` - ParentID uint64 `json:"parentId"` - Passwd string `json:"passwd"` - PciSlot uint64 `json:"pciSlot"` - Pool string `json:"pool"` - PurgeTime uint64 `json:"purgeTime"` - RealityDeviceNumber uint64 `json:"realityDeviceNumber"` - ResID string `json:"resId"` - Role string `json:"role"` - SepID uint64 `json:"sepId"` // NOTE: absent from compute/get output - SizeMax uint64 `json:"sizeMax"` - SizeUsed uint64 `json:"sizeUsed"` // sum over all snapshots of this disk to report total consumed space - Snapshots SnapshotExtendList `json:"snapshots"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - Type string `json:"type"` - VMID uint64 `json:"vmid"` +// List VNF interfaces +type ListInterfaces []ItemVNFInterface + +// List compute disks +type ListComputeDisks []ItemComputeDisk + +// Main information about compute disk +type ItemComputeDisk struct { + // CKey + CKey string `json:"_ckey"` + + // Access Control List + ACL map[string]interface{} `json:"acl"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Boot partition + BootPartition uint64 `json:"bootPartition"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // Destruction time + DestructionTime uint64 `json:"destructionTime"` + + // Disk path + DiskPath string `json:"diskPath"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Image ID + ImageID uint64 `json:"imageId"` + + // List image IDs + Images []uint64 `json:"images"` + + // IO tune + IOTune IOTune `json:"iotune"` + + // IQN + IQN string `json:"iqn"` + + // Login + Login string `json:"login"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Order + Order uint64 `json:"order"` + + // Params + Params string `json:"params"` + + // Parent ID + ParentID uint64 `json:"parentId"` + + // Password + Passwd string `json:"passwd"` + + // PCI slot + PCISlot uint64 `json:"pciSlot"` + + // Pool + Pool string `json:"pool"` + + // Purge time + PurgeTime uint64 `json:"purgeTime"` + + // Reality device number + RealityDeviceNumber uint64 `json:"realityDeviceNumber"` + + // Resource ID + ResID string `json:"resId"` + + // Role + Role string `json:"role"` + + // SepID + SepID uint64 `json:"sepId"` + + // Size max + SizeMax uint64 `json:"sizeMax"` + + //Size used + SizeUsed uint64 `json:"sizeUsed"` + + // List extend snapshots + Snapshots SnapshotExtendList `json:"snapshots"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Type + Type string `json:"type"` + + // Virtual machine ID + VMID uint64 `json:"vmid"` } +// Main information about snapshot extend type SnapshotExtend struct { - Guid string `json:"guid"` - Label string `json:"label"` - ResID string `json:"resId"` - SnapSetGuid string `json:"snapSetGuid"` + // GUID + GUID string `json:"guid"` + + // Label + Label string `json:"label"` + + // Resource ID + ResID string `json:"resId"` + + // SnapSetGUID + SnapSetGUID string `json:"snapSetGuid"` + + // SnapSetTime SnapSetTime uint64 `json:"snapSetTime"` - TimeStamp uint64 `json:"timestamp"` + + // TimeStamp + TimeStamp uint64 `json:"timestamp"` } +// List Snapshot Extend type SnapshotExtendList []SnapshotExtend +// Main information about IO tune type IOTune struct { - ReadBytesSec uint64 `json:"read_bytes_sec"` - ReadBytesSecMax uint64 `json:"read_bytes_sec_max"` - ReadIopsSec uint64 `json:"read_iops_sec"` - ReadIopsSecMax uint64 `json:"read_iops_sec_max"` - SizeIopsSec uint64 `json:"size_iops_sec"` - TotalBytesSec uint64 `json:"total_bytes_sec"` + // ReadBytesSec + ReadBytesSec uint64 `json:"read_bytes_sec"` + + // ReadBytesSecMax + ReadBytesSecMax uint64 `json:"read_bytes_sec_max"` + + // ReadIOPSSec + ReadIOPSSec uint64 `json:"read_iops_sec"` + + // ReadIOPSSecMax + ReadIOPSSecMax uint64 `json:"read_iops_sec_max"` + + // SizeIOPSSec + SizeIOPSSec uint64 `json:"size_iops_sec"` + + // TotalBytesSec + TotalBytesSec uint64 `json:"total_bytes_sec"` + + // TotalBytesSecMax TotalBytesSecMax uint64 `json:"total_bytes_sec_max"` - TotalIopsSec uint64 `json:"total_iops_sec"` - TotalIopsSecMax uint64 `json:"total_iops_sec_max"` - WriteBytesSec uint64 `json:"write_bytes_sec"` + + // TotalIOPSSec + TotalIOPSSec uint64 `json:"total_iops_sec"` + + // TotalIOPSSecMax + TotalIOPSSecMax uint64 `json:"total_iops_sec_max"` + + // WriteBytesSec + WriteBytesSec uint64 `json:"write_bytes_sec"` + + // WriteBytesSecMax WriteBytesSecMax uint64 `json:"write_bytes_sec_max"` - WriteIopsSec uint64 `json:"write_iops_sec"` - WriteIopsSecMax uint64 `json:"write_iops_sec_max"` + + // WriteIOPSSec + WriteIOPSSec uint64 `json:"write_iops_sec"` + + // WriteIOPSSecMax + WriteIOPSSecMax uint64 `json:"write_iops_sec_max"` } -type ComputeItem struct { - ACL []interface{} `json:"ACL"` - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - AffinityLabel string `json:"affinityLabel"` - AffinityRules RuleList `json:"affinityRules"` - AffinityWeight uint64 `json:"affinityWeight"` - AntiAffinityRules RuleList `json:"antiAffinityRules"` - Architecture string `json:"arch"` - BootOrder []string `json:"bootOrder"` - BootDiskSize uint64 `json:"bootdiskSize"` - CloneReference uint64 `json:"cloneReference"` - Clones []uint64 `json:"clones"` - ComputeCIID uint64 `json:"computeciId"` - CPU uint64 `json:"cpus"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - CustomFields map[string]interface{} `json:"customFields"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - Description string `json:"desc"` - Devices interface{} `json:"devices"` - Disks []uint64 `json:"disks"` - Driver string `json:"driver"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - ImageID uint64 `json:"imageId"` - ImageName string `json:"imageName"` - Intefaces IntefaceList `json:"interfaces"` - LockStatus string `json:"lockStatus"` - ManagerID uint64 `json:"managerId"` - ManagerType string `json:"managerType"` - MigrationJob uint64 `json:"migrationjob"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - Pinned bool `json:"pinned"` - RAM uint64 `json:"ram"` - ReferenceID string `json:"referenceId"` - Registered bool `json:"registered"` - ResName string `json:"resName"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - SnapSets SnapSetList `json:"snapSets"` - StatelessSepID uint64 `json:"statelessSepId"` - StatelessSepType string `json:"statelessSepType"` - Status string `json:"status"` - Tags map[string]string `json:"tags"` - TechStatus string `json:"techStatus"` - TotalDiskSize uint64 `json:"totalDisksSize"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - UserManaged bool `json:"userManaged"` - Userdata interface{} `json:"userdata"` - VGPUs []uint64 `json:"vgpus"` - VirtualImageID uint64 `json:"virtualImageId"` - VirtualImageName string `json:"virtualImageName"` +// Main information about compute +type ItemCompute struct { + // Access Control List + ACL []interface{} `json:"ACL"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Affinity label + AffinityLabel string `json:"affinityLabel"` + + // List affinity rules + AffinityRules ListRules `json:"affinityRules"` + + // Affinity weight + AffinityWeight uint64 `json:"affinityWeight"` + + // List anti affinity rules + AntiAffinityRules ListRules `json:"antiAffinityRules"` + + // Architecture + Architecture string `json:"arch"` + + // Boot order + BootOrder []string `json:"bootOrder"` + + // Boot disk size + BootDiskSize uint64 `json:"bootdiskSize"` + + // Clone reference + CloneReference uint64 `json:"cloneReference"` + + // List clone IDs + Clones []uint64 `json:"clones"` + + // Compute CI ID + ComputeCIID uint64 `json:"computeciId"` + + // Number of cores + CPU uint64 `json:"cpus"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Custom fields + CustomFields map[string]interface{} `json:"customFields"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // Devices + Devices interface{} `json:"devices"` + + // List disk IDs + Disks []uint64 `json:"disks"` + + // Driver + Driver string `json:"driver"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Image ID + ImageID uint64 `json:"imageId"` + + // Image name + ImageName string `json:"imageName"` + + // List interfaces + Interfaces ListInterfaces `json:"interfaces"` + + // Lock status + LockStatus string `json:"lockStatus"` + + // Manager ID + ManagerID uint64 `json:"managerId"` + + // Manager type + ManagerType string `json:"managerType"` + + // Migration job + MigrationJob uint64 `json:"migrationjob"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Pinned or not + Pinned bool `json:"pinned"` + + // Number of RAM + RAM uint64 `json:"ram"` + + // Reference ID + ReferenceID string `json:"referenceId"` + + // Registered + Registered bool `json:"registered"` + + // Resource name + ResName string `json:"resName"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // List snapsets + SnapSets ListSnapSets `json:"snapSets"` + + // Stateless SepID + StatelessSepID uint64 `json:"statelessSepId"` + + // Stateless SepType + StatelessSepType string `json:"statelessSepType"` + + // Status + Status string `json:"status"` + + // Tags + Tags map[string]string `json:"tags"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Total disk size + TotalDiskSize uint64 `json:"totalDisksSize"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // User Managed or not + UserManaged bool `json:"userManaged"` + + // Userdata + Userdata interface{} `json:"userdata"` + + // List vGPU IDs + VGPUs []uint64 `json:"vgpus"` + + // Virtual image ID + VirtualImageID uint64 `json:"virtualImageId"` + + // Virtual image name + VirtualImageName string `json:"virtualImageName"` } -type ComputeList []ComputeItem +// List information about computes +type ListComputes []ItemCompute diff --git a/pkg/cloudapi/compute/move_to_rg.go b/pkg/cloudapi/compute/move_to_rg.go index 5fc0803..7fb1bfc 100644 --- a/pkg/cloudapi/compute/move_to_rg.go +++ b/pkg/cloudapi/compute/move_to_rg.go @@ -7,15 +7,33 @@ import ( "strconv" ) +// Request struct for move compute new resource group type MoveToRGRequest struct { + // ID of the compute instance to move + // Required: true ComputeID uint64 `url:"computeId"` - RGID uint64 `url:"rgId"` - Name string `url:"name,omitempty"` - Autostart bool `url:"autostart,omitempty"` - ForceStop bool `url:"forceStop,omitempty"` + + // ID of the target resource group + // Required: true + RGID uint64 `url:"rgId"` + + // New name for the compute upon successful move, + // if name change required. + // Pass empty string if no name change necessary + // Required: false + Name string `url:"name,omitempty"` + + // Should the compute be restarted upon successful move + // Required: false + Autostart bool `url:"autostart,omitempty"` + + // By default moving compute in a running state is not allowed. + // Set this flag to True to force stop running compute instance prior to move. + // Required: false + ForceStop bool `url:"forceStop,omitempty"` } -func (crq MoveToRGRequest) Validate() error { +func (crq MoveToRGRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -26,8 +44,9 @@ func (crq MoveToRGRequest) Validate() error { return nil } +// MoveToRG moves compute instance to new resource group func (c Compute) MoveToRG(ctx context.Context, req MoveToRGRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -43,5 +62,6 @@ func (c Compute) MoveToRG(ctx context.Context, req MoveToRGRequest) (bool, error if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/net_attach.go b/pkg/cloudapi/compute/net_attach.go index 416542d..69bc7a3 100644 --- a/pkg/cloudapi/compute/net_attach.go +++ b/pkg/cloudapi/compute/net_attach.go @@ -9,14 +9,30 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for attach network type NetAttachRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` - NetType string `url:"netType"` - NetID uint64 `url:"netId"` - IPAddr string `url:"ipAddr,omitempty"` + + // Network type + // 'EXTNET' for connect to external network directly + // and 'VINS' for connect to ViNS + // Required: true + NetType string `url:"netType"` + + // Network ID for connect to + // For EXTNET - external network ID + // For VINS - VINS ID + // Required: true + NetID uint64 `url:"netId"` + + // Directly required IP address for new network interface + // Required: true + IPAddr string `url:"ipAddr,omitempty"` } -func (crq NetAttachRequest) Validate() error { +func (crq NetAttachRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -27,7 +43,6 @@ func (crq NetAttachRequest) Validate() error { if !validator { return errors.New("validation-error: field NetType can be only EXTNET or VINS") } - if crq.NetID == 0 { return errors.New("validation-error: field NetID can not be empty or equal to 0") } @@ -35,8 +50,9 @@ func (crq NetAttachRequest) Validate() error { return nil } -func (c Compute) NetAttach(ctx context.Context, req NetAttachRequest) (*NetAttach, error) { - err := req.Validate() +// NetAttach attach network to compute and gets info about network +func (c Compute) NetAttach(ctx context.Context, req NetAttachRequest) (*RecordNetAttach, error) { + err := req.validate() if err != nil { return nil, err } @@ -48,11 +64,12 @@ func (c Compute) NetAttach(ctx context.Context, req NetAttachRequest) (*NetAttac return nil, err } - netAttach := &NetAttach{} - err = json.Unmarshal(res, netAttach) + info := RecordNetAttach{} + + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return netAttach, nil + return &info, nil } diff --git a/pkg/cloudapi/compute/net_detach.go b/pkg/cloudapi/compute/net_detach.go index c5b4f05..bd8363a 100644 --- a/pkg/cloudapi/compute/net_detach.go +++ b/pkg/cloudapi/compute/net_detach.go @@ -7,13 +7,22 @@ import ( "strconv" ) +// Request struct for detach networ to compute type NetDetachRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` - IPAddr string `url:"ipAddr,omitempty"` - MAC string `url:"mac,omitempty"` + + // IP of the network interface + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // MAC of the network interface + // Required: false + MAC string `url:"mac,omitempty"` } -func (crq NetDetachRequest) Validate() error { +func (crq NetDetachRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -21,8 +30,9 @@ func (crq NetDetachRequest) Validate() error { return nil } +// NetDetach detach network to compute func (c Compute) NetDetach(ctx context.Context, req NetDetachRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -38,5 +48,6 @@ func (c Compute) NetDetach(ctx context.Context, req NetDetachRequest) (bool, err if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/pause.go b/pkg/cloudapi/compute/pause.go index 0e90c6f..b9633f8 100644 --- a/pkg/cloudapi/compute/pause.go +++ b/pkg/cloudapi/compute/pause.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for pause compute type PauseRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq PauseRequest) Validate() error { +func (crq PauseRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq PauseRequest) Validate() error { return nil } +// Pause pause compute func (c Compute) Pause(ctx context.Context, req PauseRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -36,5 +40,6 @@ func (c Compute) Pause(ctx context.Context, req PauseRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/pfw_add.go b/pkg/cloudapi/compute/pfw_add.go index 1aa1bf5..25326d0 100644 --- a/pkg/cloudapi/compute/pfw_add.go +++ b/pkg/cloudapi/compute/pfw_add.go @@ -9,15 +9,31 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for add port forward rule type PFWAddRequest struct { - ComputeID uint64 `url:"computeId"` + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // External start port number for the rule + // Required: true PublicPortStart uint64 `url:"publicPortStart"` - PublicPortEnd uint64 `url:"publicPortEnd,omitempty"` - LocalBasePort uint64 `url:"localBasePort"` - Proto string `url:"proto"` + + // End port number (inclusive) for the ranged rule + // Required: false + PublicPortEnd uint64 `url:"publicPortEnd,omitempty"` + + // Internal base port number + // Required: true + LocalBasePort uint64 `url:"localBasePort"` + + // Network protocol + // either "tcp" or "udp" + // Required: true + Proto string `url:"proto"` } -func (crq PFWAddRequest) Validate() error { +func (crq PFWAddRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -38,8 +54,9 @@ func (crq PFWAddRequest) Validate() error { return nil } +// PFWAdd add port forward rule func (c Compute) PFWAdd(ctx context.Context, req PFWAddRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } diff --git a/pkg/cloudapi/compute/pfw_del.go b/pkg/cloudapi/compute/pfw_del.go index bed1d20..c4d3dc8 100644 --- a/pkg/cloudapi/compute/pfw_del.go +++ b/pkg/cloudapi/compute/pfw_del.go @@ -7,16 +7,35 @@ import ( "strconv" ) +// Request struct for delete port forward rule type PFWDelRequest struct { - ComputeID uint64 `url:"computeId"` - PFWID uint64 `url:"ruleId,omitempty"` + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // ID of the rule to delete. If specified, all other arguments will be ignored + // Required: false + PFWID uint64 `url:"ruleId,omitempty"` + + // External start port number for the rule + // Required: false PublicPortStart uint64 `url:"publicPortStart,omitempty"` - PublicPortEnd uint64 `url:"publicPortEnd,omitempty"` - LocalBasePort uint64 `url:"localBasePort,omitempty"` - Proto string `url:"proto,omitempty"` + + // End port number (inclusive) for the ranged rule + // Required: false + PublicPortEnd uint64 `url:"publicPortEnd,omitempty"` + + // Internal base port number + // Required: false + LocalBasePort uint64 `url:"localBasePort,omitempty"` + + // Network protocol + // either "tcp" or "udp" + // Required: false + Proto string `url:"proto,omitempty"` } -func (crq PFWDelRequest) Validate() error { +func (crq PFWDelRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -24,8 +43,9 @@ func (crq PFWDelRequest) Validate() error { return nil } +// PFWDel delete port forward rule func (c Compute) PFWDel(ctx context.Context, req PFWDelRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/pfw_list.go b/pkg/cloudapi/compute/pfw_list.go index 3e92dde..545d639 100644 --- a/pkg/cloudapi/compute/pfw_list.go +++ b/pkg/cloudapi/compute/pfw_list.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list port forwards type PFWListRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq PFWListRequest) Validate() error { +func (crq PFWListRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq PFWListRequest) Validate() error { return nil } -func (c Compute) PFWList(ctx context.Context, req PFWListRequest) (PFWList, error) { - err := req.Validate() +// PFWList gets compute port forwards list +func (c Compute) PFWList(ctx context.Context, req PFWListRequest) (ListPFWs, error) { + err := req.validate() if err != nil { return nil, err } @@ -32,12 +36,12 @@ func (c Compute) PFWList(ctx context.Context, req PFWListRequest) (PFWList, erro return nil, err } - pfwList := PFWList{} + list := ListPFWs{} - err = json.Unmarshal(res, &pfwList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return pfwList, nil + return list, nil } diff --git a/pkg/cloudapi/compute/pin_to_stack.go b/pkg/cloudapi/compute/pin_to_stack.go index c5cc926..de19a03 100644 --- a/pkg/cloudapi/compute/pin_to_stack.go +++ b/pkg/cloudapi/compute/pin_to_stack.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for pin comptute to stack type PinToStackRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq PinToStackRequest) Validate() error { +func (crq PinToStackRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq PinToStackRequest) Validate() error { return nil } +// PinToStack pin compute to current stack func (c Compute) PinToStack(ctx context.Context, req PinToStackRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } @@ -36,5 +40,6 @@ func (c Compute) PinToStack(ctx context.Context, req PinToStackRequest) (uint64, if err != nil { return 0, err } + return result, nil } diff --git a/pkg/cloudapi/compute/power_cycle.go b/pkg/cloudapi/compute/power_cycle.go index 8ec13bc..341ed87 100644 --- a/pkg/cloudapi/compute/power_cycle.go +++ b/pkg/cloudapi/compute/power_cycle.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for force stop and start compute type PowerCycleRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq PowerCycleRequest) Validate() error { +func (crq PowerCycleRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq PowerCycleRequest) Validate() error { return nil } +// PowerCycle makes force stop and start compute func (c Compute) PowerCycle(ctx context.Context, req PowerCycleRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -36,5 +40,6 @@ func (c Compute) PowerCycle(ctx context.Context, req PowerCycleRequest) (bool, e if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/reboot.go b/pkg/cloudapi/compute/reboot.go index 290d56f..d81fea9 100644 --- a/pkg/cloudapi/compute/reboot.go +++ b/pkg/cloudapi/compute/reboot.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for reboot compute type RebootRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq RebootRequest) Validate() error { +func (crq RebootRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq RebootRequest) Validate() error { return nil } +// Reboot reboot compute func (c Compute) Reboot(ctx context.Context, req RebootRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -36,5 +40,6 @@ func (c Compute) Reboot(ctx context.Context, req RebootRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/redeploy.go b/pkg/cloudapi/compute/redeploy.go index b16cdb4..ab071b5 100644 --- a/pkg/cloudapi/compute/redeploy.go +++ b/pkg/cloudapi/compute/redeploy.go @@ -7,16 +7,35 @@ import ( "strconv" ) +// Request struct for redeploy type RedeployRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` - ImageID uint64 `url:"imageId,omitempty"` - DiskSize uint64 `url:"diskSize,omitempty"` + + // ID of the new OS image, if image change is required + // Required: false + ImageID uint64 `url:"imageId,omitempty"` + + // new size for the boot disk in GB, if boot disk size change is required + // Required: false + DiskSize uint64 `url:"diskSize,omitempty"` + + // How to handle data disks connected to this compute instance, + // KEEP, DETACH, DESTROY + // Required: false DataDisks string `url:"dataDisks,omitempty"` - AutoStart bool `url:"autoStart,omitempty"` - ForceStop bool `url:"forceStop,omitempty"` + + // Should the compute be restarted upon successful redeploy + // Required: false + AutoStart bool `url:"autoStart,omitempty"` + + // Set this flag to True to force stop running compute instance and redeploy next + // Required: false + ForceStop bool `url:"forceStop,omitempty"` } -func (crq RedeployRequest) Validate() error { +func (crq RedeployRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -24,8 +43,9 @@ func (crq RedeployRequest) Validate() error { return nil } +// Redeploy redeploy compute func (c Compute) Redeploy(ctx context.Context, req RedeployRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -41,5 +61,6 @@ func (c Compute) Redeploy(ctx context.Context, req RedeployRequest) (bool, error if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/reset.go b/pkg/cloudapi/compute/reset.go index 81c86db..05f797f 100644 --- a/pkg/cloudapi/compute/reset.go +++ b/pkg/cloudapi/compute/reset.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for reset compute type ResetRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq ResetRequest) Validate() error { +func (crq ResetRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq ResetRequest) Validate() error { return nil } +// Reset reset compute func (c Compute) Reset(ctx context.Context, req ResetRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -36,5 +40,6 @@ func (c Compute) Reset(ctx context.Context, req ResetRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/resize.go b/pkg/cloudapi/compute/resize.go index 6dc1e49..a514852 100644 --- a/pkg/cloudapi/compute/resize.go +++ b/pkg/cloudapi/compute/resize.go @@ -7,14 +7,28 @@ import ( "strconv" ) +// Request struct for resize compute type ResizeRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` - Force bool `url:"force,omitempty"` - CPU uint64 `url:"cpu,omitempty"` - RAM uint64 `url:"ram,omitempty"` + + // New CPU count. + // Pass 0 if no change to CPU count is required + // Required: false + Force bool `url:"force,omitempty"` + + // New RAM volume in MB. + // Pass 0 if no change to RAM volume is required + // Required: false + CPU uint64 `url:"cpu,omitempty"` + + // Force compute resize + // Required: false + RAM uint64 `url:"ram,omitempty"` } -func (crq ResizeRequest) Validate() error { +func (crq ResizeRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -22,8 +36,9 @@ func (crq ResizeRequest) Validate() error { return nil } +// Resize resize compute instance func (c Compute) Resize(ctx context.Context, req ResizeRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -39,5 +54,6 @@ func (c Compute) Resize(ctx context.Context, req ResizeRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/restore.go b/pkg/cloudapi/compute/restore.go index f9799e2..2f7c534 100644 --- a/pkg/cloudapi/compute/restore.go +++ b/pkg/cloudapi/compute/restore.go @@ -6,11 +6,14 @@ import ( "net/http" ) +// Request struct for restore compute type RestoreRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq RestoreRequest) Validate() error { +func (crq RestoreRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -18,8 +21,9 @@ func (crq RestoreRequest) Validate() error { return nil } +// Restore restore compute from recycle bin func (c Compute) Restore(ctx context.Context, req RestoreRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } diff --git a/pkg/cloudapi/compute/resume.go b/pkg/cloudapi/compute/resume.go index 6415f7f..6bf5dcc 100644 --- a/pkg/cloudapi/compute/resume.go +++ b/pkg/cloudapi/compute/resume.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for resume compute type ResumeRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq ResumeRequest) Validate() error { +func (crq ResumeRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq ResumeRequest) Validate() error { return nil } +// Resume resume Compute from paused state func (c Compute) Resume(ctx context.Context, req ResumeRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -36,5 +40,6 @@ func (c Compute) Resume(ctx context.Context, req ResumeRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/snapshot_create.go b/pkg/cloudapi/compute/snapshot_create.go index f64ad82..7cddb37 100644 --- a/pkg/cloudapi/compute/snapshot_create.go +++ b/pkg/cloudapi/compute/snapshot_create.go @@ -7,12 +7,19 @@ import ( "strings" ) +// Request struct for create snapshot type SnapshotCreateRequest struct { + // ID of the compute instance to create snapshot for + // Required: true ComputeID uint64 `url:"computeId"` - Label string `url:"label"` + + // Text label for snapshot. + // Must be unique among this compute snapshots + // Required: true + Label string `url:"label"` } -func (crq SnapshotCreateRequest) Validate() error { +func (crq SnapshotCreateRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -23,8 +30,9 @@ func (crq SnapshotCreateRequest) Validate() error { return nil } +// SnapshotCreate create compute snapshot func (c Compute) SnapshotCreate(ctx context.Context, req SnapshotCreateRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } diff --git a/pkg/cloudapi/compute/snapshot_delete.go b/pkg/cloudapi/compute/snapshot_delete.go index cd94ec5..6d744c4 100644 --- a/pkg/cloudapi/compute/snapshot_delete.go +++ b/pkg/cloudapi/compute/snapshot_delete.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for delete snapshot type SnapshotDeleteRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` - Label string `url:"label"` + + // Text label of snapshot to delete + // Required: true + Label string `url:"label"` } -func (crq SnapshotDeleteRequest) Validate() error { +func (crq SnapshotDeleteRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -23,8 +29,9 @@ func (crq SnapshotDeleteRequest) Validate() error { return nil } +// SnapshotDelete delete specified compute snapshot func (c Compute) SnapshotDelete(ctx context.Context, req SnapshotDeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/snapshot_list.go b/pkg/cloudapi/compute/snapshot_list.go index 55230cf..9dd7dcc 100644 --- a/pkg/cloudapi/compute/snapshot_list.go +++ b/pkg/cloudapi/compute/snapshot_list.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list snapshots type SnapshotListRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq SnapshotListRequest) Validate() error { +func (crq SnapshotListRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq SnapshotListRequest) Validate() error { return nil } -func (c Compute) SnapshotList(ctx context.Context, req SnapshotListRequest) (SnapshotList, error) { - err := req.Validate() +// SnapshotList gets list compute snapshots +func (c Compute) SnapshotList(ctx context.Context, req SnapshotListRequest) (ListSnapShots, error) { + err := req.validate() if err != nil { return nil, err } @@ -32,12 +36,12 @@ func (c Compute) SnapshotList(ctx context.Context, req SnapshotListRequest) (Sna return nil, err } - snapshotList := SnapshotList{} + list := ListSnapShots{} - err = json.Unmarshal(res, &snapshotList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return snapshotList, nil + return list, nil } diff --git a/pkg/cloudapi/compute/snapshot_rollback.go b/pkg/cloudapi/compute/snapshot_rollback.go index 62ae6cc..e25d0a9 100644 --- a/pkg/cloudapi/compute/snapshot_rollback.go +++ b/pkg/cloudapi/compute/snapshot_rollback.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for rollback type SnapshotRollbackRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` - Label string `url:"label"` + + // Text label of snapshot to rollback + // Required: true + Label string `url:"label"` } -func (crq SnapshotRollbackRequest) Validate() error { +func (crq SnapshotRollbackRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -23,8 +29,9 @@ func (crq SnapshotRollbackRequest) Validate() error { return nil } +// SnapshotRollback rollback specified compute snapshot func (c Compute) SnapshotRollback(ctx context.Context, req SnapshotRollbackRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/compute/snapshot_usage.go b/pkg/cloudapi/compute/snapshot_usage.go index 1568a30..91248bd 100644 --- a/pkg/cloudapi/compute/snapshot_usage.go +++ b/pkg/cloudapi/compute/snapshot_usage.go @@ -7,12 +7,19 @@ import ( "net/http" ) +// Request struct for get compute snapshot real size on storage type SnapshotUsageRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` - Label string `url:"label,omitempty"` + + // Specify to show usage exact for this snapshot. + // Leave empty for get usage for all compute snapshots + // Required: false + Label string `url:"label,omitempty"` } -func (crq SnapshotUsageRequest) Validate() error { +func (crq SnapshotUsageRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -20,8 +27,11 @@ func (crq SnapshotUsageRequest) Validate() error { return nil } -func (c Compute) SnapshotUsage(ctx context.Context, req SnapshotUsageRequest) (SnapshotUsageList, error) { - err := req.Validate() +// SnapshotUsage Get compute snapshot real size on storage. +// Always returns list of json objects, and first json object contains summary about all related +// snapshots. +func (c Compute) SnapshotUsage(ctx context.Context, req SnapshotUsageRequest) (ListUsageSnapshots, error) { + err := req.validate() if err != nil { return nil, err } @@ -33,12 +43,12 @@ func (c Compute) SnapshotUsage(ctx context.Context, req SnapshotUsageRequest) (S return nil, err } - snapshotUsage := SnapshotUsageList{} + list := ListUsageSnapshots{} - err = json.Unmarshal(res, &snapshotUsage) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return snapshotUsage, nil + return list, nil } diff --git a/pkg/cloudapi/compute/start.go b/pkg/cloudapi/compute/start.go index 5facbc9..a307064 100644 --- a/pkg/cloudapi/compute/start.go +++ b/pkg/cloudapi/compute/start.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for start compute type StartRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` + + // ID of CD-ROM live image to boot + // Required: false AltBootID uint64 `url:"altBootId,omitempty"` } -func (crq StartRequest) Validate() error { +func (crq StartRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -20,8 +26,9 @@ func (crq StartRequest) Validate() error { return nil } +// Start starts compute func (c Compute) Start(ctx context.Context, req StartRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -37,5 +44,6 @@ func (c Compute) Start(ctx context.Context, req StartRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/stop.go b/pkg/cloudapi/compute/stop.go index 9ebc460..5147f1a 100644 --- a/pkg/cloudapi/compute/stop.go +++ b/pkg/cloudapi/compute/stop.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for stop compute type StopRequest struct { + // ID of compute instance + // Required: true ComputeID uint64 `url:"computeId"` - Force bool `url:"force,omitempty"` + + // Force stop compute + // Required: false + Force bool `url:"force,omitempty"` } -func (crq StopRequest) Validate() error { +func (crq StopRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -20,8 +26,9 @@ func (crq StopRequest) Validate() error { return nil } +// Stop stops compute func (c Compute) Stop(ctx context.Context, req StopRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -37,5 +44,6 @@ func (c Compute) Stop(ctx context.Context, req StopRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/tag_add.go b/pkg/cloudapi/compute/tag_add.go index 32fb418..245d4ce 100644 --- a/pkg/cloudapi/compute/tag_add.go +++ b/pkg/cloudapi/compute/tag_add.go @@ -7,20 +7,28 @@ import ( "strconv" ) +// Request struct for add tag to compute type TagAddRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` - Key string `url:"key"` - Value string `url:"value"` + + // Tag key + // Required: true + Key string `url:"key"` + + // Tag value + // Required: true + Value string `url:"value"` } -func (crq TagAddRequest) Validate() error { +func (crq TagAddRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } if crq.Key == "" { return errors.New("validation-error: field Key can not be empty") } - if crq.Value == "" { return errors.New("validation-error: field Value can not be empty") } @@ -28,8 +36,9 @@ func (crq TagAddRequest) Validate() error { return nil } +// TagAdd add tag to compute tags dict func (c Compute) TagAdd(ctx context.Context, req TagAddRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -45,5 +54,6 @@ func (c Compute) TagAdd(ctx context.Context, req TagAddRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/tag_remove.go b/pkg/cloudapi/compute/tag_remove.go index 4cfebec..f3f09ef 100644 --- a/pkg/cloudapi/compute/tag_remove.go +++ b/pkg/cloudapi/compute/tag_remove.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for remove tag from compute type TagRemoveRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` - Key string `url:"key"` + + // Tag key + // Required: true + Key string `url:"key"` } -func (crq TagRemoveRequest) Validate() error { +func (crq TagRemoveRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -23,8 +29,9 @@ func (crq TagRemoveRequest) Validate() error { return nil } +// TagRemove removes tag from compute tags dict func (c Compute) TagRemove(ctx context.Context, req TagRemoveRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -40,5 +47,6 @@ func (c Compute) TagRemove(ctx context.Context, req TagRemoveRequest) (bool, err if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/unpin_from_stack.go b/pkg/cloudapi/compute/unpin_from_stack.go index b4d9eb2..bcae4fc 100644 --- a/pkg/cloudapi/compute/unpin_from_stack.go +++ b/pkg/cloudapi/compute/unpin_from_stack.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for unpin from stack type UnpinFromStackRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` } -func (crq UnpinFromStackRequest) Validate() error { +func (crq UnpinFromStackRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (crq UnpinFromStackRequest) Validate() error { return nil } +// UnpinFromStack unpin compute from current stack func (c Compute) UnpinFromStack(ctx context.Context, req UnpinFromStackRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -36,5 +40,6 @@ func (c Compute) UnpinFromStack(ctx context.Context, req UnpinFromStackRequest) if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/update.go b/pkg/cloudapi/compute/update.go index 9b53f58..2051fa7 100644 --- a/pkg/cloudapi/compute/update.go +++ b/pkg/cloudapi/compute/update.go @@ -7,13 +7,22 @@ import ( "strconv" ) +// Request struct for update compute type UpdateRequest struct { - ComputeID uint64 `url:"computeId"` - Name string `url:"name,omitempty"` + // ID of the compute + // Required: true + ComputeID uint64 `url:"computeId"` + + // New name + // Required: false + Name string `url:"name,omitempty"` + + // New description + // Required: false Description string `url:"desc,omitempty"` } -func (crq UpdateRequest) Validate() error { +func (crq UpdateRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -21,8 +30,9 @@ func (crq UpdateRequest) Validate() error { return nil } +// Update updates some properties of the compute func (c Compute) Update(ctx context.Context, req UpdateRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -38,5 +48,6 @@ func (c Compute) Update(ctx context.Context, req UpdateRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/user_grant.go b/pkg/cloudapi/compute/user_grant.go index 413d65a..735788a 100644 --- a/pkg/cloudapi/compute/user_grant.go +++ b/pkg/cloudapi/compute/user_grant.go @@ -9,21 +9,32 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for grant access to compute type UserGrantRequest struct { - ComputeID uint64 `url:"computeId"` - Username string `url:"userName"` + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Name of the user to add + // Required: true + Username string `url:"userName"` + + // Access type + // Should be one of: + // - 'R' for Read only + // - 'RCX' for Write + // - 'ARCXDU' for Admin + // Required: true AccessType string `url:"accesstype"` } -func (crq UserGrantRequest) Validate() error { +func (crq UserGrantRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } - if crq.Username == "" { return errors.New("validation-error: field UserName can not be empty") } - if crq.AccessType == "" { return errors.New("validation-error: field AccessType can not be empty") } @@ -35,8 +46,9 @@ func (crq UserGrantRequest) Validate() error { return nil } +// UserGrant grant user access to the compute func (c Compute) UserGrant(ctx context.Context, req UserGrantRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -52,5 +64,6 @@ func (c Compute) UserGrant(ctx context.Context, req UserGrantRequest) (bool, err if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/user_list.go b/pkg/cloudapi/compute/user_list.go index 8e4b83a..f417ce6 100644 --- a/pkg/cloudapi/compute/user_list.go +++ b/pkg/cloudapi/compute/user_list.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list users for compute type UserListRequest struct { - ComputeID uint64 `url:"computeId "` + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` } -func (crq UserListRequest) Validate() error { +func (crq UserListRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } @@ -19,7 +22,12 @@ func (crq UserListRequest) Validate() error { return nil } -func (c Compute) UserList(ctx context.Context, req UserListRequest) (*UserList, error) { +// UserList gets users list for compute +func (c Compute) UserList(ctx context.Context, req UserListRequest) (*RecordACL, error) { + err := req.validate() + if err != nil { + return nil, err + } url := "/cloudapi/compute/userList" @@ -28,12 +36,12 @@ func (c Compute) UserList(ctx context.Context, req UserListRequest) (*UserList, return nil, err } - userList := &UserList{} + list := RecordACL{} - err = json.Unmarshal(res, userList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return userList, nil + return &list, nil } diff --git a/pkg/cloudapi/compute/user_revoke.go b/pkg/cloudapi/compute/user_revoke.go index 4b7bbd5..1425635 100644 --- a/pkg/cloudapi/compute/user_revoke.go +++ b/pkg/cloudapi/compute/user_revoke.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for revoke user access type UserRevokeRequest struct { + // ID of the compute instance + // Required: true ComputeID uint64 `url:"computeId"` - Username string `url:"userName"` + + // Name of the user to remove + // Required: true + Username string `url:"userName"` } -func (crq UserRevokeRequest) Validate() error { +func (crq UserRevokeRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } - if crq.Username == "" { return errors.New("validation-error: field UserName can not be empty") } @@ -24,8 +29,9 @@ func (crq UserRevokeRequest) Validate() error { return nil } +// UserRevoke revokes user access to the compute func (c Compute) UserRevoke(ctx context.Context, req UserRevokeRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -41,5 +47,6 @@ func (c Compute) UserRevoke(ctx context.Context, req UserRevokeRequest) (bool, e if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/compute/user_update.go b/pkg/cloudapi/compute/user_update.go index c8d2c77..a210aa3 100644 --- a/pkg/cloudapi/compute/user_update.go +++ b/pkg/cloudapi/compute/user_update.go @@ -9,21 +9,32 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for update user access type UserUpdateRequest struct { - ComputeID uint64 `url:"computeId"` - Username string `url:"userName"` + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Name of the user to update + // Required: true + Username string `url:"userName"` + + // Access type + // Should be one of: + // - 'R' for Read only + // - 'RCX' for Write + // - 'ARCXDU' for Admin + // Required: true AccessType string `url:"accesstype"` } -func (crq UserUpdateRequest) Validate() error { +func (crq UserUpdateRequest) validate() error { if crq.ComputeID == 0 { return errors.New("validation-error: field ComputeID can not be empty or equal to 0") } - if crq.Username == "" { return errors.New("validation-error: field UserName can not be empty") } - if crq.AccessType == "" { return errors.New("validation-error: field AccessType can not be empty") } @@ -35,8 +46,9 @@ func (crq UserUpdateRequest) Validate() error { return nil } +// UserUpdate updates user access to the compute func (c Compute) UserUpdate(ctx context.Context, req UserUpdateRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -52,5 +64,6 @@ func (c Compute) UserUpdate(ctx context.Context, req UserUpdateRequest) (bool, e if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/computeci.go b/pkg/cloudapi/computeci.go index e534b8d..86c5404 100644 --- a/pkg/cloudapi/computeci.go +++ b/pkg/cloudapi/computeci.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudapi/computeci" ) -func (ca *CloudApi) ComputeCI() *computeci.ComputeCI { +// Accessing the ComputeCI method group +func (ca *CloudAPI) ComputeCI() *computeci.ComputeCI { return computeci.New(ca.client) } diff --git a/pkg/cloudapi/computeci/computeci.go b/pkg/cloudapi/computeci/computeci.go index d22e349..47c5873 100644 --- a/pkg/cloudapi/computeci/computeci.go +++ b/pkg/cloudapi/computeci/computeci.go @@ -1,13 +1,16 @@ +// API Actor for managing ComputeCI. This actor is a final API for admin to manage ComputeCI package computeci import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to computeci type ComputeCI struct { client interfaces.Caller } +// Builder for computeci endpoints func New(client interfaces.Caller) *ComputeCI { return &ComputeCI{ client, diff --git a/pkg/cloudapi/computeci/get.go b/pkg/cloudapi/computeci/get.go index 8c274b6..7ec69ad 100644 --- a/pkg/cloudapi/computeci/get.go +++ b/pkg/cloudapi/computeci/get.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for information about computeci type GetRequest struct { + // ID of the Compute CI + // Required: true ComputeCIID uint64 `url:"computeciId"` } -func (krq GetRequest) Validate() error { +func (krq GetRequest) validate() error { if krq.ComputeCIID == 0 { return errors.New("field ComputeCIID can not be empty or equal to 0") } @@ -19,21 +22,26 @@ func (krq GetRequest) Validate() error { return nil } -func (c ComputeCI) Get(ctx context.Context, req GetRequest) (*ComputeCIRecord, error) { - if err := req.Validate(); err != nil { +// Get gets information about computeci by ID +func (c ComputeCI) Get(ctx context.Context, req GetRequest) (*ItemComputeCI, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/computeci/get" - computeciRaw, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - computeci := &ComputeCIRecord{} - if err := json.Unmarshal(computeciRaw, computeci); err != nil { + info := ItemComputeCI{} + + err = json.Unmarshal(res, &info) + if err != nil { return nil, err } - return computeci, nil + return &info, nil } diff --git a/pkg/cloudapi/computeci/list.go b/pkg/cloudapi/computeci/list.go index cded5b0..1b85f30 100644 --- a/pkg/cloudapi/computeci/list.go +++ b/pkg/cloudapi/computeci/list.go @@ -6,23 +6,36 @@ import ( "net/http" ) +// Request struct for get list of computeci type ListRequest struct { - IncludeDeleted bool `url:"includeDeleted,omitempty"` - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` + // If true list deleted instances as well + // Required: false + IncludeDeleted bool `url:"includeDeleted,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (c ComputeCI) List(ctx context.Context, req ListRequest) (ComputeCIList, error) { +// List gets list of computeci instances +func (c ComputeCI) List(ctx context.Context, req ListRequest) (ListComputeCI, error) { url := "/cloudapi/computeci/list" - computeciListRaw, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - computeciList := ComputeCIList{} - if err := json.Unmarshal(computeciListRaw, &computeciList); err != nil { + list := ListComputeCI{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return computeciList, nil + return list, nil } diff --git a/pkg/cloudapi/computeci/models.go b/pkg/cloudapi/computeci/models.go index 48f1d22..c96f917 100644 --- a/pkg/cloudapi/computeci/models.go +++ b/pkg/cloudapi/computeci/models.go @@ -1,14 +1,31 @@ package computeci -type ComputeCIRecord struct { +// Main information about computeci +type ItemComputeCI struct { + // Custom fields CustomFields map[string]interface{} `json:"customFields"` - Description string `json:"desc"` - Drivers []string `json:"drivers"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - Name string `json:"name"` - Status string `json:"status"` - Template string `jsnn:"template"` + + // Description + Description string `json:"desc"` + + // List drivers + Drivers []string `json:"drivers"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Status + Status string `json:"status"` + + // Template + Template string `jsnn:"template"` } -type ComputeCIList []ComputeCIRecord +// List of computeci instances +type ListComputeCI []ItemComputeCI diff --git a/pkg/cloudapi/disks.go b/pkg/cloudapi/disks.go index 28d33a7..f67f5ee 100644 --- a/pkg/cloudapi/disks.go +++ b/pkg/cloudapi/disks.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudapi/disks" ) -func (ca *CloudApi) Disks() *disks.Disks { +// Accessing the Disks method group +func (ca *CloudAPI) Disks() *disks.Disks { return disks.New(ca.client) } diff --git a/pkg/cloudapi/disks/create.go b/pkg/cloudapi/disks/create.go index aabf921..fd69850 100644 --- a/pkg/cloudapi/disks/create.go +++ b/pkg/cloudapi/disks/create.go @@ -9,20 +9,53 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for create disk type CreateRequest struct { - AccountID uint64 `url:"accountId"` - GID uint64 `url:"gid"` - Name string `url:"name"` + // ID of the account + // Required: true + AccountID uint64 `url:"accountId"` + + // ID of the grid (platform) + // Required: true + GID uint64 `url:"gid"` + + // Name of disk + // Required: true + Name string `url:"name"` + + // Description of disk + // Required: false Description string `url:"description,omitempty"` - Size uint64 `url:"size,omitempty"` - Type string `url:"type"` - SSDSize uint64 `url:"ssdSize,omitempty"` - IOps uint64 `url:"iops"` - SepID uint64 `url:"sep_id,omitempty"` - Pool string `url:"pool,omitempty"` + + // Size in GB, default is 0 + // Required: false + Size uint64 `url:"size,omitempty"` + + // Type of disk + // - B=Boot + // - D=Data + // - T=Temp + // Required: true + Type string `url:"type"` + + // Size in GB default is 0 + // Required: false + SSDSize uint64 `url:"ssdSize,omitempty"` + + // Max IOPS disk can perform defaults to 2000 + // Required: false + IOPS uint64 `url:"iops,omitempty"` + + // Storage endpoint provider ID to create disk + // Required: false + SEPID uint64 `url:"sep_id,omitempty"` + + // Pool name to create disk + // Required: false + Pool string `url:"pool,omitempty"` } -func (drq CreateRequest) Validate() error { +func (drq CreateRequest) validate() error { if drq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -32,21 +65,17 @@ func (drq CreateRequest) Validate() error { if drq.Name == "" { return errors.New("validation-error: field Name can not be empty") } - validType := validators.StringInSlice(drq.Type, []string{"B", "D", "T"}) if !validType { return errors.New("validation-error: field Type must be set as B, D or T") } - if drq.IOps == 0 { - return errors.New("validation-error: field IOps must be set") - } - return nil } +// Create creates a disk func (d Disks) Create(ctx context.Context, req CreateRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } @@ -62,6 +91,6 @@ func (d Disks) Create(ctx context.Context, req CreateRequest) (uint64, error) { if err != nil { return 0, err } - return result, nil + return result, nil } diff --git a/pkg/cloudapi/disks/delete.go b/pkg/cloudapi/disks/delete.go index c3349b4..7ec618b 100644 --- a/pkg/cloudapi/disks/delete.go +++ b/pkg/cloudapi/disks/delete.go @@ -7,23 +7,36 @@ import ( "strconv" ) +// Request for delete disk type DeleteRequest struct { - DiskID uint64 `url:"diskId"` - Detach bool `url:"detach,omitempty"` - Permanently bool `url:"permanently,omitempty"` - Reason string `url:"reason,omitempty"` -} + // ID of disk to delete + // Required: true + DiskID uint64 `url:"diskId"` + + // Detach disk from machine first + // Required: false + Detach bool `url:"detach,omitempty"` + + // Whether to completely delete the disk, works only with non attached disks + // Required: false + Permanently bool `url:"permanently,omitempty"` -func (d DeleteRequest) Validate() error { + // Reason to delete + // Required: false + Reason string `url:"reason,omitempty"` +} +func (d DeleteRequest) validate() error { if d.DiskID == 0 { return errors.New("validation-error: field DiskID must be set") } + return nil } +// Delete deletes disk by ID func (d Disks) Delete(ctx context.Context, req DeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -39,5 +52,6 @@ func (d Disks) Delete(ctx context.Context, req DeleteRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/disks/delete_disks.go b/pkg/cloudapi/disks/delete_disks.go index 931d9dd..c5b646a 100644 --- a/pkg/cloudapi/disks/delete_disks.go +++ b/pkg/cloudapi/disks/delete_disks.go @@ -7,22 +7,35 @@ import ( "strconv" ) +// Request struct for multiple disks type DisksDeleteRequest struct { - DisksIDs []uint64 `url:"diskIds"` - Reason string `url:"reason"` - Permanently bool `url:"permanently"` + // List of disk ids to delete + // Required: true + DisksIDs []uint64 `url:"diskIds"` + + // Reason for deleting the disks + // Required: true + Reason string `url:"reason"` + + // Whether to completely delete the disks, works only with non attached disks + // Required: false + Permanently bool `url:"permanently,omitempty"` } -func (drq DisksDeleteRequest) Validate() error { +func (drq DisksDeleteRequest) validate() error { if len(drq.DisksIDs) == 0 { return errors.New("validation-error: field DisksIDs must include one or more disks ids") } + if drq.Reason == "" { + return errors.New("validation-error: field Reason must be set") + } return nil } +// DeleteDisks deletes multiple disks permanently func (d Disks) DeleteDisks(ctx context.Context, req DisksDeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -40,5 +53,4 @@ func (d Disks) DeleteDisks(ctx context.Context, req DisksDeleteRequest) (bool, e } return result, nil - } diff --git a/pkg/cloudapi/disks/disks.go b/pkg/cloudapi/disks/disks.go index ce07806..55c100d 100644 --- a/pkg/cloudapi/disks/disks.go +++ b/pkg/cloudapi/disks/disks.go @@ -1,13 +1,16 @@ +// API Actor api, this actor is the final api a enduser uses to manage his resources package disks import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to disks type Disks struct { client interfaces.Caller } +// Builder for disks endpoints func New(client interfaces.Caller) *Disks { return &Disks{ client, diff --git a/pkg/cloudapi/disks/get.go b/pkg/cloudapi/disks/get.go index 4897f8a..a36dccc 100644 --- a/pkg/cloudapi/disks/get.go +++ b/pkg/cloudapi/disks/get.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get information about disk type GetRequest struct { + // ID of the disk + // Required: true DiskID uint64 `url:"diskId"` } -func (drq GetRequest) Validate() error { +func (drq GetRequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID can not be empty or equal to 0") } @@ -19,8 +22,10 @@ func (drq GetRequest) Validate() error { return nil } -func (d Disks) Get(ctx context.Context, req GetRequest) (*DiskRecord, error) { - err := req.Validate() +// Get gets disk details +// Notice: the devicename field is the name as it is passed to the kernel (kname in linux) for unattached disks this field has no relevant value +func (d Disks) Get(ctx context.Context, req GetRequest) (*RecordDisk, error) { + err := req.validate() if err != nil { return nil, err } @@ -32,13 +37,12 @@ func (d Disks) Get(ctx context.Context, req GetRequest) (*DiskRecord, error) { return nil, err } - disk := &DiskRecord{} + info := RecordDisk{} - err = json.Unmarshal(res, disk) + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return disk, nil - + return &info, nil } diff --git a/pkg/cloudapi/disks/limitio.go b/pkg/cloudapi/disks/limitio.go index 8cab664..9e48c83 100644 --- a/pkg/cloudapi/disks/limitio.go +++ b/pkg/cloudapi/disks/limitio.go @@ -7,25 +7,70 @@ import ( "strconv" ) +// Request struct for limit IO type LimitIORequest struct { - DiskID uint64 `url:"diskId"` - IOps uint64 `url:"iops"` - TotalBytesSec uint64 `url:"total_bytes_sec"` - ReadBytesSec uint64 `url:"read_bytes_sec"` - WriteBytesSec uint64 `url:"write_bytes_sec"` - TotalIOpsSec uint64 `url:"total_iops_sec"` - ReadIOpsSec uint64 `url:"read_iops_sec"` - WriteIOpsSec uint64 `url:"write_iops_sec"` - TotalBytesSecMax uint64 `url:"total_bytes_sec_max"` - ReadBytesSecMax uint64 `url:"read_bytes_sec_max"` - WriteBytesSecMax uint64 `url:"write_bytes_sec_max"` - TotalIOpsSecMax uint64 `url:"total_iops_sec_max"` - ReadIOpsSecMax uint64 `url:"read_iops_sec_max"` - WriteIOpsSecMax uint64 `url:"write_iops_sec_max"` - SizeIOpsSec uint64 `url:"size_iops_sec"` + // ID of the disk to limit + // Required: true + DiskID uint64 `url:"diskId"` + + // Alias for total_iops_sec for backwards compatibility + // Required: false + IOPS uint64 `url:"iops,omitempty"` + + // TotalBytesSec + // Required: false + TotalBytesSec uint64 `url:"total_bytes_sec,omitempty"` + + // ReadBytesSec + // Required: false + ReadBytesSec uint64 `url:"read_bytes_sec,omitempty"` + + // WriteBytesSec + // Required: false + WriteBytesSec uint64 `url:"write_bytes_sec,omitempty"` + + // TotalIOPSSec + // Required: false + TotalIOPSSec uint64 `url:"total_iops_sec,omitempty"` + + // ReadIOPSSec + // Required: false + ReadIOPSSec uint64 `url:"read_iops_sec,omitempty"` + + // WriteIOPSSec + // Required: false + WriteIOPSSec uint64 `url:"write_iops_sec,omitempty"` + + // TotalBytesSecMax + // Required: false + TotalBytesSecMax uint64 `url:"total_bytes_sec_max,omitempty"` + + // ReadBytesSecMax + // Required: false + ReadBytesSecMax uint64 `url:"read_bytes_sec_max,omitempty"` + + // WriteBytesSecMax + // Required: false + WriteBytesSecMax uint64 `url:"write_bytes_sec_max,omitempty"` + + // TotalIOPSSecMax + // Required: false + TotalIOPSSecMax uint64 `url:"total_iops_sec_max,omitempty"` + + // ReadIOPSSecMax + // Required: false + ReadIOPSSecMax uint64 `url:"read_iops_sec_max,omitempty"` + + // WriteIOPSSecMax + // Required: false + WriteIOPSSecMax uint64 `url:"write_iops_sec_max,omitempty"` + + // SizeIOPSSec + // Required: false + SizeIOPSSec uint64 `url:"size_iops_sec,omitempty"` } -func (drq LimitIORequest) Validate() error { +func (drq LimitIORequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID can not be empty or equal to 0") } @@ -33,8 +78,11 @@ func (drq LimitIORequest) Validate() error { return nil } +// LimitIO limit IO for a certain disk +// total and read/write options are not allowed to be combined +// see http://libvirt.org/formatdomain.html#elementsDisks iotune section for more details func (d Disks) LimitIO(ctx context.Context, req LimitIORequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -52,5 +100,4 @@ func (d Disks) LimitIO(ctx context.Context, req LimitIORequest) (bool, error) { } return result, nil - } diff --git a/pkg/cloudapi/disks/list.go b/pkg/cloudapi/disks/list.go index 358c242..5c21c8e 100644 --- a/pkg/cloudapi/disks/list.go +++ b/pkg/cloudapi/disks/list.go @@ -6,14 +6,27 @@ import ( "net/http" ) +// Request struct for get list/list_deleted of disks type ListRequest struct { + // ID of the account the disks belong to + // Required: false AccountID uint64 `url:"accountId,omitempty"` - Type string `url:"type,omitempty"` - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` + + // Type of the disks + // Required: false + Type string `url:"type,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (d Disks) List(ctx context.Context, req ListRequest) (DiskList, error) { +// List gets list the created disks belonging to an account +func (d Disks) List(ctx context.Context, req ListRequest) (ListDisks, error) { url := "/cloudapi/disks/list" res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req) @@ -21,34 +34,31 @@ func (d Disks) List(ctx context.Context, req ListRequest) (DiskList, error) { return nil, err } - diskList := DiskList{} + list := ListDisks{} - err = json.Unmarshal(res, &diskList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return diskList, nil - + return list, nil } -func (d Disks) ListDeleted(ctx context.Context, req ListRequest) (DiskList, error) { - url := "/disks/listDeleted" - prefix := "/cloudapi" +// ListDeleted gets list the deleted disks belonging to an account +func (d Disks) ListDeleted(ctx context.Context, req ListRequest) (ListDisks, error) { + url := "/cloudapi/disks/listDeleted" - url = prefix + url res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - diskList := DiskList{} + list := ListDisks{} - err = json.Unmarshal(res, &diskList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return diskList, nil - + return list, nil } diff --git a/pkg/cloudapi/disks/list_types.go b/pkg/cloudapi/disks/list_types.go index 08047dc..b49c13a 100644 --- a/pkg/cloudapi/disks/list_types.go +++ b/pkg/cloudapi/disks/list_types.go @@ -6,10 +6,14 @@ import ( "net/http" ) +// Request struct for get list types of disks type ListTypesRequest struct { + // Show detailed disk types by seps + // Required: false Detailed bool `url:"detailed"` } +// ListTypes gets list defined disk types func (d Disks) ListTypes(ctx context.Context, req ListTypesRequest) ([]interface{}, error) { url := "/cloudapi/disks/listTypes" @@ -18,13 +22,12 @@ func (d Disks) ListTypes(ctx context.Context, req ListTypesRequest) ([]interface return nil, err } - typesList := make([]interface{}, 0) + list := make([]interface{}, 0) - err = json.Unmarshal(res, &typesList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return typesList, nil - + return list, nil } diff --git a/pkg/cloudapi/disks/list_unattached.go b/pkg/cloudapi/disks/list_unattached.go index 622a073..e37e393 100644 --- a/pkg/cloudapi/disks/list_unattached.go +++ b/pkg/cloudapi/disks/list_unattached.go @@ -6,11 +6,15 @@ import ( "net/http" ) +// Request struct for get list unattached disk type ListUnattachedRequest struct { - AccountID uint64 `url:"accountId"` + // ID of the account + // Required: false + AccountID uint64 `url:"accountId,omitempty"` } -func (d Disks) ListUnattached(ctx context.Context, req ListUnattachedRequest) (DiskList, error) { +// ListUnattached gets list of unattached disks +func (d Disks) ListUnattached(ctx context.Context, req ListUnattachedRequest) (ListDisks, error) { url := "/cloudapi/disks/listUnattached" res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req) @@ -18,13 +22,12 @@ func (d Disks) ListUnattached(ctx context.Context, req ListUnattachedRequest) (D return nil, err } - diskList := DiskList{} + list := ListDisks{} - err = json.Unmarshal(res, &diskList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return diskList, nil - + return list, nil } diff --git a/pkg/cloudapi/disks/models.go b/pkg/cloudapi/disks/models.go index 9ad69bf..318d054 100644 --- a/pkg/cloudapi/disks/models.go +++ b/pkg/cloudapi/disks/models.go @@ -1,116 +1,280 @@ package disks -type Disk struct { - ACL map[string]interface{} `json:"acl"` - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - BootPartition uint64 `json:"bootPartition"` - CreatedTime uint64 `json:"createdTime"` - ComputeID uint64 `json:"computeId"` - ComputeName string `json:"computeName"` - DeletedTime uint64 `json:"deletedTime"` - DeviceName string `json:"devicename"` - Description string `json:"desc"` - DestructionTime uint64 `json:"destructionTime"` - GID uint64 `json:"gid"` - ID uint64 `json:"id"` - ImageID uint64 `json:"imageId"` - Images []uint64 `json:"images"` - IOTune IOTune `json:"iotune"` - MachineID uint64 `json:"machineId"` - MachineName string `json:"machineName"` - Name string `json:"name"` - Order uint64 `json:"order"` - Params string `json:"params"` - ParentID uint64 `json:"parentId"` - PciSlot uint64 `json:"pciSlot"` - Pool string `json:"pool"` - PurgeTime uint64 `json:"purgeTime"` - ResID string `json:"resId"` - ResName string `json:"resName"` - Role string `json:"role"` - SepType string `json:"sepType"` - SepID uint64 `json:"sepId"` // NOTE: absent from compute/get output - SizeMax uint64 `json:"sizeMax"` - Snapshots []Snapshot `json:"snapshots"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - Type string `json:"type"` - VMID uint64 `json:"vmid"` +// Main information about disk +type ItemDisk struct { + // Access Control List + ACL map[string]interface{} `json:"acl"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Boot partition + BootPartition uint64 `json:"bootPartition"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Compute ID + ComputeID uint64 `json:"computeId"` + + // Compute name + ComputeName string `json:"computeName"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Device name + DeviceName string `json:"devicename"` + + // Description + Description string `json:"desc"` + + // Destruction time + DestructionTime uint64 `json:"destructionTime"` + + // Grid ID + GID uint64 `json:"gid"` + + // ID + ID uint64 `json:"id"` + + // Image ID + ImageID uint64 `json:"imageId"` + + // List of image IDs + Images []uint64 `json:"images"` + + // IOTune + IOTune IOTune `json:"iotune"` + + // Machine ID + MachineID uint64 `json:"machineId"` + + // Machine name + MachineName string `json:"machineName"` + + // Name + Name string `json:"name"` + + // Order + Order uint64 `json:"order"` + + // Params + Params string `json:"params"` + + // Parent ID + ParentID uint64 `json:"parentId"` + + // PCI slot + PCISlot uint64 `json:"pciSlot"` + + // Pool + Pool string `json:"pool"` + + // Purge time + PurgeTime uint64 `json:"purgeTime"` + + // Resource ID + ResID string `json:"resId"` + + // Resource name + ResName string `json:"resName"` + + // Role + Role string `json:"role"` + + // SepType + SepType string `json:"sepType"` + + // SepID + SepID uint64 `json:"sepId"` + + // Size max + SizeMax uint64 `json:"sizeMax"` + + // List of snapshots + Snapshots ListSnapshots `json:"snapshots"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Type + Type string `json:"type"` + + // Virtual machine ID + VMID uint64 `json:"vmid"` } -type Snapshot struct { - Guid string `json:"guid"` - Label string `json:"label"` - ResID string `json:"resId"` - SnapSetGuid string `json:"snapSetGuid"` +// List of disks +type ListDisks []ItemDisk + +// Main information about snapshot +type ItemSnapshot struct { + // GUID + GUID string `json:"guid"` + + // Label + Label string `json:"label"` + + // Resource ID + ResID string `json:"resId"` + + // SnapSetGUID + SnapSetGUID string `json:"snapSetGuid"` + + // SnapSetTime SnapSetTime uint64 `json:"snapSetTime"` - TimeStamp uint64 `json:"timestamp"` + + // TimeStamp + TimeStamp uint64 `json:"timestamp"` } -type SnapshotList []Snapshot +// List of snapshots +type ListSnapshots []ItemSnapshot +// Main information about IO tune type IOTune struct { - ReadBytesSec uint64 `json:"read_bytes_sec"` - ReadBytesSecMax uint64 `json:"read_bytes_sec_max"` - ReadIopsSec uint64 `json:"read_iops_sec"` - ReadIopsSecMax uint64 `json:"read_iops_sec_max"` - SizeIopsSec uint64 `json:"size_iops_sec"` - TotalBytesSec uint64 `json:"total_bytes_sec"` + // ReadBytesSec + ReadBytesSec uint64 `json:"read_bytes_sec"` + + // ReadBytesSecMax + ReadBytesSecMax uint64 `json:"read_bytes_sec_max"` + + // ReadIOPSSec + ReadIOPSSec uint64 `json:"read_iops_sec"` + + // ReadIOPSSecMax + ReadIOPSSecMax uint64 `json:"read_iops_sec_max"` + + // SizeIOPSSec + SizeIOPSSec uint64 `json:"size_iops_sec"` + + // TotalBytesSec + TotalBytesSec uint64 `json:"total_bytes_sec"` + + // TotalBytesSecMax TotalBytesSecMax uint64 `json:"total_bytes_sec_max"` - TotalIopsSec uint64 `json:"total_iops_sec"` - TotalIopsSecMax uint64 `json:"total_iops_sec_max"` - WriteBytesSec uint64 `json:"write_bytes_sec"` + + // TotalIOPSSec + TotalIOPSSec uint64 `json:"total_iops_sec"` + + // TotalIOPSSecMax + TotalIOPSSecMax uint64 `json:"total_iops_sec_max"` + + // WriteBytesSec + WriteBytesSec uint64 `json:"write_bytes_sec"` + + // WriteBytesSecMax WriteBytesSecMax uint64 `json:"write_bytes_sec_max"` - WriteIopsSec uint64 `json:"write_iops_sec"` - WriteIopsSecMax uint64 `json:"write_iops_sec_max"` + + // WriteIOPSSec + WriteIOPSSec uint64 `json:"write_iops_sec"` + + // WriteIOPSSecMax + WriteIOPSSecMax uint64 `json:"write_iops_sec_max"` } -type DiskList []Disk +// Detailed information about disk +type RecordDisk struct { + // Access Control List + ACL map[string]interface{} `json:"acl"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Device name + DeviceName string `json:"devicename"` + + // Description + Description string `json:"desc"` + + // Destruction time + DestructionTime uint64 `json:"destructionTime"` + + // Grid ID + GID uint64 `json:"gid"` + + // ID + ID uint64 `json:"id"` -type DisksTypesListCoomon []string + // Image ID + ImageID uint64 `json:"imageId"` -type DisksTypesListDetailed struct { - Pools []Pool `json:"pools"` + // List of image IDs + Images []uint64 `json:"images"` + + // IOTune + IOTune IOTune `json:"iotune"` + + // Name + Name string `json:"name"` + + // Order + Order uint64 `json:"order"` + + // Params + Params string `json:"params"` + + // Parent ID + ParentID uint64 `json:"parentId"` + + // PCI slot + PCISlot uint64 `json:"pciSlot"` + + // Pool + Pool string `json:"pool"` + + // Purge time + PurgeTime uint64 `json:"purgeTime"` + + // Resource ID + ResID string `json:"resId"` + + // Resource name + ResName string `json:"resName"` + + // Role + Role string `json:"role"` + + // SepType + SepType string `json:"sepType"` + + // SepID SepID uint64 `json:"sepId"` -} -type Pool struct { - Name string `json:"name"` - Types []string `json:"types"` -} + // Size max + SizeMax uint64 `json:"sizeMax"` + + // Size used + SizeUsed uint64 `json:"sizeUsed"` + + // List of snapshots + Snapshots ListSnapshots `json:"snapshots"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Type + Type string `json:"type"` -type DiskRecord struct { - ACL map[string]interface{} `json:"acl"` - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - CreatedTime uint64 `json:"createdTime"` - DeletedTime uint64 `json:"deletedTime"` - DeviceName string `json:"devicename"` - Description string `json:"desc"` - DestructionTime uint64 `json:"destructionTime"` - GID uint64 `json:"gid"` - ID uint64 `json:"id"` - ImageID uint64 `json:"imageId"` - Images []uint64 `json:"images"` - IOTune IOTune `json:"iotune"` - Name string `json:"name"` - Order uint64 `json:"order"` - Params string `json:"params"` - ParentID uint64 `json:"parentId"` - PciSlot uint64 `json:"pciSlot"` - Pool string `json:"pool"` - PurgeTime uint64 `json:"purgeTime"` - ResID string `json:"resId"` - ResName string `json:"resName"` - Role string `json:"role"` - SepType string `json:"sepType"` - SepID uint64 `json:"sepId"` // NOTE: absent from compute/get output - SizeMax uint64 `json:"sizeMax"` - SizeUsed uint64 `json:"sizeUsed"` // sum over all snapshots of this disk to report total consumed space - Snapshots []Snapshot `json:"snapshots"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - Type string `json:"type"` - VMID uint64 `json:"vmid"` + // Virtual machine ID + VMID uint64 `json:"vmid"` } diff --git a/pkg/cloudapi/disks/rename.go b/pkg/cloudapi/disks/rename.go index 4a1a56b..298dded 100644 --- a/pkg/cloudapi/disks/rename.go +++ b/pkg/cloudapi/disks/rename.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for rename disk type RenameRequest struct { + // ID of the disk to rename + // Required: true DiskID uint64 `url:"diskId"` - Name string `url:"name"` + + // New name of disk + // Required: true + Name string `url:"name"` } -func (drq RenameRequest) Validate() error { +func (drq RenameRequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID can not be empty or equal to 0") } - if drq.Name == "" { return errors.New("validation-error: field Name can not be empty") } @@ -24,8 +29,9 @@ func (drq RenameRequest) Validate() error { return nil } +// Rename rename disk func (d Disks) Rename(ctx context.Context, req RenameRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -43,5 +49,4 @@ func (d Disks) Rename(ctx context.Context, req RenameRequest) (bool, error) { } return result, nil - } diff --git a/pkg/cloudapi/disks/resize.go b/pkg/cloudapi/disks/resize.go index 50feb23..87560b8 100644 --- a/pkg/cloudapi/disks/resize.go +++ b/pkg/cloudapi/disks/resize.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for resize disk type ResizeRequest struct { + // ID of the disk to resize + // Required: true DiskID uint64 `url:"diskId"` - Size uint64 `url:"size"` + + // New size of the disk in GB + // Required: true + Size uint64 `url:"size"` } -func (drq ResizeRequest) Validate() error { +func (drq ResizeRequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID can not be empty or equal to 0") } - if drq.Size == 0 { return errors.New("validation-error: field Size can not be empty or equal to 0") } @@ -24,8 +29,12 @@ func (drq ResizeRequest) Validate() error { return nil } +// Resize resize disk +// Returns 200 if disk is resized online, else will return 202, +// in that case please stop and start your machine after changing the disk size, for your changes to be reflected. +// This method will not be used for disks, assigned to computes. Only unassigned disks and disks, assigned with "old" virtual machines. func (d Disks) Resize(ctx context.Context, req ResizeRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -43,19 +52,20 @@ func (d Disks) Resize(ctx context.Context, req ResizeRequest) (bool, error) { } return result, nil - } +// Resize2 resize disk +// Returns 200 if disk is resized online, else will return 202, +// in that case please stop and start your machine after changing the disk size, for your changes to be reflected. +// This method will not be used for disks, assigned to "old" virtual machines. Only unassigned disks and disks, assigned with computes. func (d Disks) Resize2(ctx context.Context, req ResizeRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } - url := "/disks/resize2" - prefix := "/cloudapi" + url := "/cloudapi/disks/resize2" - url = prefix + url res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err @@ -67,5 +77,4 @@ func (d Disks) Resize2(ctx context.Context, req ResizeRequest) (bool, error) { } return result, nil - } diff --git a/pkg/cloudapi/disks/restore.go b/pkg/cloudapi/disks/restore.go index 31f364f..df4380b 100644 --- a/pkg/cloudapi/disks/restore.go +++ b/pkg/cloudapi/disks/restore.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for restore a deleted unattached disk type RestoreRequest struct { + // ID of the disk to restore + // Required: true DiskID uint64 `url:"diskId"` + + // Reason for restoring the disk + // Required: true Reason string `url:"reason"` } -func (drq RestoreRequest) Validate() error { +func (drq RestoreRequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID can not be empty or equal to 0") } - if drq.Reason == "" { return errors.New("validation-error: field Reason can not be empty") } @@ -24,8 +29,9 @@ func (drq RestoreRequest) Validate() error { return nil } +// Restore restore a deleted unattached disk from recycle bin func (d Disks) Restore(ctx context.Context, req RestoreRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -43,5 +49,4 @@ func (d Disks) Restore(ctx context.Context, req RestoreRequest) (bool, error) { } return result, nil - } diff --git a/pkg/cloudapi/disks/search.go b/pkg/cloudapi/disks/search.go index a5dc26a..d33bb28 100644 --- a/pkg/cloudapi/disks/search.go +++ b/pkg/cloudapi/disks/search.go @@ -6,13 +6,22 @@ import ( "net/http" ) +// Request struct for search type SearchRequest struct { + // ID of the account to search for the Disk + // Required: false AccountID uint64 `url:"accountId,omitempty"` - Name string `url:"name,omitempty"` - ShowAll bool `url:"show_all,omitempty"` + // Name of the Disk to search for + // Required: false + Name string `url:"name,omitempty"` + + // If false, then disks having one of the statuses are not listed + // Required: false + ShowAll bool `url:"show_all,omitempty"` } -func (d Disks) Search(ctx context.Context, req SearchRequest) (DiskList, error) { +// Search search disks +func (d Disks) Search(ctx context.Context, req SearchRequest) (ListDisks, error) { url := "/cloudapi/disks/search" res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req) @@ -20,13 +29,12 @@ func (d Disks) Search(ctx context.Context, req SearchRequest) (DiskList, error) return nil, err } - diskList := DiskList{} + list := ListDisks{} - err = json.Unmarshal(res, &diskList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return diskList, nil - + return list, nil } diff --git a/pkg/cloudapi/disks/snapshot_delete.go b/pkg/cloudapi/disks/snapshot_delete.go index 03db348..3848c2e 100644 --- a/pkg/cloudapi/disks/snapshot_delete.go +++ b/pkg/cloudapi/disks/snapshot_delete.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for delete snapshot type SnapshotDeleteRequest struct { + // ID of disk to delete + // Required: true DiskID uint64 `url:"diskId"` - Label string `url:"label"` + + // Label of the snapshot to delete + // Required: false + Label string `url:"label"` } -func (drq SnapshotDeleteRequest) Validate() error { +func (drq SnapshotDeleteRequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID can not be empty or equal to 0") } @@ -24,8 +30,9 @@ func (drq SnapshotDeleteRequest) Validate() error { return nil } +// SnapshotDelete deletes a snapshot func (d Disks) SnapshotDelete(ctx context.Context, req SnapshotDeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -43,5 +50,4 @@ func (d Disks) SnapshotDelete(ctx context.Context, req SnapshotDeleteRequest) (b } return result, nil - } diff --git a/pkg/cloudapi/disks/snapshot_rollback.go b/pkg/cloudapi/disks/snapshot_rollback.go index 2b91a2c..5c415fb 100644 --- a/pkg/cloudapi/disks/snapshot_rollback.go +++ b/pkg/cloudapi/disks/snapshot_rollback.go @@ -7,17 +7,25 @@ import ( "strconv" ) +// Request struct for rollback snapshot type SnapshotRollbackRequest struct { - DiskID uint64 `url:"diskId"` - Label string `url:"label"` + // ID of the disk + // Required: true + DiskID uint64 `url:"diskId"` + + // Label of the snapshot to rollback + // Required: true + Label string `url:"label"` + + // Timestamp of the snapshot to rollback + // Required: true TimeStamp uint64 `url:"timestamp"` } -func (drq SnapshotRollbackRequest) Validate() error { +func (drq SnapshotRollbackRequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID can not be empty or equal to 0") } - if drq.Label == "" && drq.TimeStamp == 0 { return errors.New("validation-error: field Label or field TimeStamp can not be empty") } @@ -25,8 +33,9 @@ func (drq SnapshotRollbackRequest) Validate() error { return nil } +// SnapshotRollback rollback an individual disk snapshot func (d Disks) SnapshotRollback(ctx context.Context, req SnapshotRollbackRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/extnet.go b/pkg/cloudapi/extnet.go index d03508a..7c25c0e 100644 --- a/pkg/cloudapi/extnet.go +++ b/pkg/cloudapi/extnet.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudapi/extnet" ) -func (ca *CloudApi) ExtNet() *extnet.ExtNet { +// Accessing the ExtNet method group +func (ca *CloudAPI) ExtNet() *extnet.ExtNet { return extnet.New(ca.client) } diff --git a/pkg/cloudapi/extnet/extnet.go b/pkg/cloudapi/extnet/extnet.go index 88a0d14..41d6699 100644 --- a/pkg/cloudapi/extnet/extnet.go +++ b/pkg/cloudapi/extnet/extnet.go @@ -1,13 +1,16 @@ +// API Actor for use external networks package extnet import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to extnet type ExtNet struct { client interfaces.Caller } +// Builder for extnet endpoints func New(client interfaces.Caller) *ExtNet { return &ExtNet{ client, diff --git a/pkg/cloudapi/extnet/get.go b/pkg/cloudapi/extnet/get.go index a3f67a0..bcc7b5a 100644 --- a/pkg/cloudapi/extnet/get.go +++ b/pkg/cloudapi/extnet/get.go @@ -7,36 +7,41 @@ import ( "net/http" ) +// Request struct for get detailed information about external network type GetRequest struct { + // ID of external network + // Required: true NetID uint64 `url:"net_id"` } -func (erq GetRequest) Validate() error { +func (erq GetRequest) validate() error { if erq.NetID == 0 { return errors.New("validation-error: field NetID can not be empty or equal to 0") } + return nil } -func (e ExtNet) Get(ctx context.Context, req GetRequest) (*ExtNetDetailed, error) { - err := req.Validate() +// Get gets detailed information about external network +func (e ExtNet) Get(ctx context.Context, req GetRequest) (*RecordExtNet, error) { + err := req.validate() if err != nil { return nil, err } url := "/cloudapi/extnet/get" - extnetRaw, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - extnet := &ExtNetDetailed{} - err = json.Unmarshal(extnetRaw, &extnet) + info := RecordExtNet{} + + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return extnet, nil - + return &info, nil } diff --git a/pkg/cloudapi/extnet/get_default.go b/pkg/cloudapi/extnet/get_default.go index 1f7e948..98b6628 100644 --- a/pkg/cloudapi/extnet/get_default.go +++ b/pkg/cloudapi/extnet/get_default.go @@ -6,6 +6,7 @@ import ( "strconv" ) +// GetDefault get default external network ID func (e ExtNet) GetDefault(ctx context.Context) (uint64, error) { url := "/cloudapi/extnet/getDefault" @@ -20,5 +21,4 @@ func (e ExtNet) GetDefault(ctx context.Context) (uint64, error) { } return result, nil - } diff --git a/pkg/cloudapi/extnet/list.go b/pkg/cloudapi/extnet/list.go index d987726..ff6f542 100644 --- a/pkg/cloudapi/extnet/list.go +++ b/pkg/cloudapi/extnet/list.go @@ -6,26 +6,36 @@ import ( "net/http" ) +// Request struct for get list external network type ListRequest struct { - AccountID uint64 `url:"accountId"` - Page uint64 `url:"page"` - Size uint64 `url:"size"` + // Filter by account ID + // Required: false + AccountID uint64 `url:"accountId,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (e ExtNet) List(ctx context.Context, req ListRequest) (ExtNetList, error) { +// List gets list all available external networks +func (e ExtNet) List(ctx context.Context, req ListRequest) (ListExtNets, error) { url := "/cloudapi/extnet/list" - extnetListRaw, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - extnetList := ExtNetList{} - err = json.Unmarshal(extnetListRaw, &extnetList) + list := ListExtNets{} + + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return extnetList, nil - + return list, nil } diff --git a/pkg/cloudapi/extnet/list_computes.go b/pkg/cloudapi/extnet/list_computes.go index 855e527..2660a5f 100644 --- a/pkg/cloudapi/extnet/list_computes.go +++ b/pkg/cloudapi/extnet/list_computes.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list computes type ListComputesRequest struct { + // Filter by account ID + // Required: true AccountID uint64 `url:"accountId"` } -func (erq ListComputesRequest) Validate() error { +func (erq ListComputesRequest) validate() error { if erq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -19,20 +22,26 @@ func (erq ListComputesRequest) Validate() error { return nil } -func (e ExtNet) ListComputes(ctx context.Context, req ListComputesRequest) (ExtNetComputesList, error) { +// ListComputes gets computes from account with extnets +func (e ExtNet) ListComputes(ctx context.Context, req ListComputesRequest) (ListExtNetComputes, error) { + err := req.validate() + if err != nil { + return nil, err + } + url := "/cloudapi/extnet/listComputes" - extnetComputesListRaw, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - extnetComputesList := ExtNetComputesList{} - err = json.Unmarshal(extnetComputesListRaw, &extnetComputesList) + list := ListExtNetComputes{} + + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return extnetComputesList, nil - + return list, nil } diff --git a/pkg/cloudapi/extnet/models.go b/pkg/cloudapi/extnet/models.go index 32a703d..d6ef6f4 100644 --- a/pkg/cloudapi/extnet/models.go +++ b/pkg/cloudapi/extnet/models.go @@ -1,80 +1,195 @@ package extnet -type ExtNetRecord struct { - ID uint64 `json:"id"` - IPCidr string `json:"ipcidr"` - Name string `json:"name"` +// Main information about external network +type ItemExtNet struct { + // ID + ID uint64 `json:"id"` + + // IPCIDR + IPCIDR string `json:"ipcidr"` + + // Name + Name string `json:"name"` + + // Status + Status string `json:"status"` } -type ExtNetExtend struct { - ExtNetRecord + +// Extend information about external network +type ItemExtNetExtend struct { + // Main information about external network + ItemExtNet + + // IP address IPAddr string `json:"ipaddr"` } -type ExtNetList []ExtNetRecord -type ExtNetExtendList []ExtNetExtend - -type ExtNetComputes struct { - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - ExtNets ExtNetExtendList `json:"extnets"` - ID uint64 `json:"id"` - Name string `json:"name"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` +// List of information about external network +type ListExtNets []ItemExtNet + +// List of extend information about external network +type ListExtNetExtends []ItemExtNetExtend + +// Main information about compute with external network +type ItemExtNetCompute struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // List of extend information about external network + ExtNets ListExtNetExtends `json:"extnets"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` } -type ExtNetComputesList []ExtNetComputes +// List of information about computes with external network +type ListExtNetComputes []ItemExtNetCompute -type ExtNetQos struct { - ERate uint64 `json:"eRate"` - GUID string `json:"guid"` +// QOS +type QOS struct { + // ERate + ERate uint64 `json:"eRate"` + + // GUID + GUID string `json:"guid"` + + // InBurst InBurst uint64 `json:"inBurst"` - InRate uint64 `json:"inRate"` + + // InRate + InRate uint64 `json:"inRate"` } -type ExtNetReservation struct { - ClientType string `json:"clientType"` +// Main information about reservations +type ItemReservation struct { + // ClientType + ClientType string `json:"clientType"` + + // Description Description string `json:"desc"` - DomainName string `json:"domainname"` - HostName string `json:"hostname"` - IP string `json:"ip"` - MAC string `json:"mac"` - Type string `json:"type"` - VMID uint64 `json:"vmId"` + + // Domain name + DomainName string `json:"domainname"` + + // Hostname + Hostname string `json:"hostname"` + + // IP + IP string `json:"ip"` + + // MAC + MAC string `json:"mac"` + + // Type + Type string `json:"type"` + + // Virtual machine ID + VMID uint64 `json:"vmId"` } -type ExtNetReservations []ExtNetReservation +// List of information about reservations +type ListReservations []ItemReservation -type ExtNetVNFS struct { +// VNFs +type VNFs struct { DHCP uint64 `json:"dhcp"` } -type ExtNetDetailed struct { - CKey string `json:"_ckey"` - Meta []interface{} `json:"_meta"` - CheckIPs []string `json:"checkIPs"` - CheckIps []string `json:"checkIps"` - Default bool `json:"default"` - DefaultQos ExtNetQos `json:"defaultQos"` - Description string `json:"desc"` - Dns []string `json:"dns"` - Excluded []string `json:"excluded"` - FreeIps uint64 `json:"free_ips"` - Gateway string `json:"gateway"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - IPCidr string `json:"ipcidr"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - Network string `json:"network"` - NetworkID uint64 `json:"networkId"` - PreReservationsNum uint64 `json:"preReservationsNum"` - Prefix uint64 `json:"prefix"` - PriVNFDevID uint64 `json:"priVnfDevId"` - Reservations ExtNetReservations `json:"reservations"` - SharedWith []uint64 `json:"sharedWith"` - Status string `json:"status"` - VlanID uint64 `json:"vlanId"` - VNFS ExtNetVNFS `json:"vnfs"` +// Detailed information about external network +type RecordExtNet struct { + // CKey + CKey string `json:"_ckey"` + + // Meta + Meta []interface{} `json:"_meta"` + + // CheckIPs + CheckIPs []string `json:"checkIPs"` + + // CheckIps + CheckIps []string `json:"checkIps"` + + // Default + Default bool `json:"default"` + + // Default QOS + DefaultQOS QOS `json:"defaultQos"` + + // Description + Description string `json:"desc"` + + // list of DNS + DNS []string `json:"dns"` + + // Excluded + Excluded []string `json:"excluded"` + + // Free IPs + FreeIPs uint64 `json:"free_ips"` + + // Gateway + Gateway string `json:"gateway"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // IPCIDR + IPCIDR string `json:"ipcidr"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Network + Network string `json:"network"` + + // Network ID + NetworkID uint64 `json:"networkId"` + + // OVS Bridge + OVSBridge string `json:"ovsBridge"` + + // PreReservation IP num + PreReservationsNum uint64 `json:"preReservationsNum"` + + // Prefix + Prefix uint64 `json:"prefix"` + + // PriVNFDevID + PriVNFDevID uint64 `json:"priVnfDevId"` + + // List reservations + Reservations ListReservations `json:"reservations"` + + // Shared with + SharedWith []uint64 `json:"sharedWith"` + + // Status + Status string `json:"status"` + + // VLAN ID + VLANID uint64 `json:"vlanId"` + + // VNFs + VNFs VNFs `json:"vnfs"` } diff --git a/pkg/cloudapi/flipgroup.go b/pkg/cloudapi/flipgroup.go index b15a3fb..412ed1c 100644 --- a/pkg/cloudapi/flipgroup.go +++ b/pkg/cloudapi/flipgroup.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudapi/flipgroup" ) -func (ca *CloudApi) FlipGroup() *flipgroup.FlipGroup { +// Accessing the FLIPGroup method group +func (ca *CloudAPI) FLIPGroup() *flipgroup.FLIPGroup { return flipgroup.New(ca.client) } diff --git a/pkg/cloudapi/flipgroup/compute_add.go b/pkg/cloudapi/flipgroup/compute_add.go index 5138ece..0ea12e6 100644 --- a/pkg/cloudapi/flipgroup/compute_add.go +++ b/pkg/cloudapi/flipgroup/compute_add.go @@ -7,14 +7,20 @@ import ( "strconv" ) +// Request struct for add compute instance type ComputeAddRequest struct { - FlipGroupID uint64 `url:"flipgroupId"` - ComputeID uint64 `url:"computeId"` + // ID of the Floating IP group to add compute instance to + // Required: true + FLIPGroupID uint64 `url:"flipgroupId"` + + // ID of the compute instance to add to this group + // Required: true + ComputeID uint64 `url:"computeId"` } -func (frq ComputeAddRequest) Validate() error { - if frq.FlipGroupID == 0 { - return errors.New("field FlipGroupID can not be empty or equal to 0") +func (frq ComputeAddRequest) validate() error { + if frq.FLIPGroupID == 0 { + return errors.New("field FLIPGroupID can not be empty or equal to 0") } if frq.ComputeID == 0 { return errors.New("field ComputeID can not be empty or equal to 0") @@ -23,12 +29,15 @@ func (frq ComputeAddRequest) Validate() error { return nil } -func (f FlipGroup) ComputeAdd(ctx context.Context, req ComputeAddRequest) (bool, error) { - if err := req.Validate(); err != nil { +// ComputeAdd add compute instance to the Floating IP group +func (f FLIPGroup) ComputeAdd(ctx context.Context, req ComputeAddRequest) (bool, error) { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/flipgroup/computeAdd" + res, err := f.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err diff --git a/pkg/cloudapi/flipgroup/compute_remove.go b/pkg/cloudapi/flipgroup/compute_remove.go index 20a6a29..12637b0 100644 --- a/pkg/cloudapi/flipgroup/compute_remove.go +++ b/pkg/cloudapi/flipgroup/compute_remove.go @@ -7,14 +7,20 @@ import ( "strconv" ) +// Request struct for remove compute instance type ComputeRemoveRequest struct { - FlipGroupID uint64 `url:"flipgroupId"` - ComputeID uint64 `url:"computeId"` + // ID of the Floating IP group to remove compute instance from + // Required: true + FLIPGroupID uint64 `url:"flipgroupId"` + + // ID of the compute instance to remove + // Required: true + ComputeID uint64 `url:"computeId"` } -func (frq ComputeRemoveRequest) Validate() error { - if frq.FlipGroupID == 0 { - return errors.New("field FlipGroupID can not be empty or equal to 0") +func (frq ComputeRemoveRequest) validate() error { + if frq.FLIPGroupID == 0 { + return errors.New("field FLIPGroupID can not be empty or equal to 0") } if frq.ComputeID == 0 { return errors.New("field ComputeID can not be empty or equal to 0") @@ -23,12 +29,15 @@ func (frq ComputeRemoveRequest) Validate() error { return nil } -func (f FlipGroup) ComputeRemove(ctx context.Context, req ComputeRemoveRequest) (bool, error) { - if err := req.Validate(); err != nil { +// ComputeRemove remove compute instance from the Floating IP group +func (f FLIPGroup) ComputeRemove(ctx context.Context, req ComputeRemoveRequest) (bool, error) { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/flipgroup/computeRemove" + res, err := f.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err diff --git a/pkg/cloudapi/flipgroup/create.go b/pkg/cloudapi/flipgroup/create.go index 70d48de..8efa419 100644 --- a/pkg/cloudapi/flipgroup/create.go +++ b/pkg/cloudapi/flipgroup/create.go @@ -9,17 +9,43 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for create FLIPGroup type CreateRequest struct { - AccountID uint64 `url:"accountId"` - Name string `url:"name"` - NetType string `url:"netType"` - NetID uint64 `url:"netId"` - ClientType string `url:"clientType"` - IP string `url:"ip,omitempty"` + // Account ID + // Required: true + AccountID uint64 `url:"accountId"` + + // FLIPGroup name + // Required: true + Name string `url:"name"` + + // Network type + // Should be one of: + // - EXTNET + // - VINS + // Required: true + NetType string `url:"netType"` + + // ID of external network or VINS + // Required: true + NetID uint64 `url:"netId"` + + // Type of client + // - 'compute' + // - 'vins' (will be later) + // Required: true + ClientType string `url:"clientType"` + + // IP address to associate with this group. If empty, the platform will autoselect IP address + // Required: false + IP string `url:"ip,omitempty"` + + // Text description of this FLIPGorup instance + // Required: false Description string `url:"desc,omitempty"` } -func (frq CreateRequest) Validate() error { +func (frq CreateRequest) validate() error { if frq.AccountID == 0 { return errors.New("field AccountID can not be empty or equal to 0") } @@ -29,7 +55,6 @@ func (frq CreateRequest) Validate() error { if frq.Name == "" { return errors.New("field Name can not be empty") } - validator := validators.StringInSlice(frq.NetType, []string{"EXTNET", "VINS"}) if !validator { return errors.New("field Name can be only EXTNET or VINS") @@ -42,21 +67,26 @@ func (frq CreateRequest) Validate() error { return nil } -func (f FlipGroup) Create(ctx context.Context, req CreateRequest) (*FlipGroupRecord, error) { - if err := req.Validate(); err != nil { +// Create method will create a new FLIPGorup in the specified Account +func (f FLIPGroup) Create(ctx context.Context, req CreateRequest) (*RecordFLIPGroup, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/flipgroup/create" - fgRaw, err := f.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := f.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - fg := &FlipGroupRecord{} - if err := json.Unmarshal(fgRaw, fg); err != nil { + info := RecordFLIPGroup{} + + err = json.Unmarshal(res, &info) + if err != nil { return nil, err } - return fg, nil + return &info, nil } diff --git a/pkg/cloudapi/flipgroup/delete.go b/pkg/cloudapi/flipgroup/delete.go index 9cc30c5..a4e5253 100644 --- a/pkg/cloudapi/flipgroup/delete.go +++ b/pkg/cloudapi/flipgroup/delete.go @@ -7,24 +7,30 @@ import ( "strconv" ) +// Request struct for delete FLIPGroup type DeleteRequest struct { - FlipGroupID uint64 `url:"flipgroupId"` + // FLIPGroup ID + // Required: true + FLIPGroupID uint64 `url:"flipgroupId"` } -func (frq DeleteRequest) Validate() error { - if frq.FlipGroupID == 0 { - return errors.New("field FlipGroupID can not be empty or equal to 0") +func (frq DeleteRequest) validate() error { + if frq.FLIPGroupID == 0 { + return errors.New("field FLIPGroupID can not be empty or equal to 0") } return nil } -func (f FlipGroup) Delete(ctx context.Context, req DeleteRequest) (bool, error) { - if err := req.Validate(); err != nil { +// Delete method wil delete Floating IP group +func (f FLIPGroup) Delete(ctx context.Context, req DeleteRequest) (bool, error) { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/flipgroup/delete" + res, err := f.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err diff --git a/pkg/cloudapi/flipgroup/edit.go b/pkg/cloudapi/flipgroup/edit.go index c703d04..19dc426 100644 --- a/pkg/cloudapi/flipgroup/edit.go +++ b/pkg/cloudapi/flipgroup/edit.go @@ -7,26 +7,38 @@ import ( "strconv" ) +// Request struct for edit FLIPGroup type EditRequest struct { - FlipGroupID uint64 `url:"flipgroupId"` - Name string `url:"name,omitempty"` + // FLIPGroup ID + // Required: true + FLIPGroupID uint64 `url:"flipgroupId"` + + // FLIPGroup name + // Required: true + Name string `url:"name,omitempty"` + + // FLIPGroup description + // Required: true Description string `url:"desc,omitempty"` } -func (frq EditRequest) Validate() error { - if frq.FlipGroupID == 0 { - return errors.New("field FlipGroupID can not be empty or equal to 0") +func (frq EditRequest) validate() error { + if frq.FLIPGroupID == 0 { + return errors.New("field FLIPGroupID can not be empty or equal to 0") } return nil } -func (f FlipGroup) Edit(ctx context.Context, req EditRequest) (bool, error) { - if err := req.Validate(); err != nil { +// Edit edits FLIPGroup fields +func (f FLIPGroup) Edit(ctx context.Context, req EditRequest) (bool, error) { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/flipgroup/edit" + res, err := f.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err diff --git a/pkg/cloudapi/flipgroup/flipgroup.go b/pkg/cloudapi/flipgroup/flipgroup.go index b51829e..ae168e6 100644 --- a/pkg/cloudapi/flipgroup/flipgroup.go +++ b/pkg/cloudapi/flipgroup/flipgroup.go @@ -1,15 +1,18 @@ +// API to manage FLIPGroup instances package flipgroup import ( "github.com/rudecs/decort-sdk/interfaces" ) -type FlipGroup struct { +// Structure for creating request to FLIPGroup +type FLIPGroup struct { client interfaces.Caller } -func New(client interfaces.Caller) *FlipGroup { - return &FlipGroup{ +// Builder for FLIPGroup endpoints +func New(client interfaces.Caller) *FLIPGroup { + return &FLIPGroup{ client, } } diff --git a/pkg/cloudapi/flipgroup/get.go b/pkg/cloudapi/flipgroup/get.go index 96a7501..332f6b5 100644 --- a/pkg/cloudapi/flipgroup/get.go +++ b/pkg/cloudapi/flipgroup/get.go @@ -7,34 +7,41 @@ import ( "net/http" ) +// Request struct for get information about FLIPGroup type GetRequest struct { - FlipGroupID uint64 `url:"flipgroupId"` + // FLIPGroup ID + // Required: true + FLIPGroupID uint64 `url:"flipgroupId"` } -func (frq GetRequest) Validate() error { - if frq.FlipGroupID == 0 { - return errors.New("field FlipGroupID can not be empty or equal to 0") +func (frq GetRequest) validate() error { + if frq.FLIPGroupID == 0 { + return errors.New("field FLIPGroupID can not be empty or equal to 0") } return nil } -func (f FlipGroup) Get(ctx context.Context, req GetRequest) (*FlipGroupItem, error) { - if err := req.Validate(); err != nil { +// Get gets details of the specified Floating IP group +func (f FLIPGroup) Get(ctx context.Context, req GetRequest) (*ItemFLIPGroup, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/flipgroup/get" + res, err := f.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - fg := &FlipGroupItem{} - err = json.Unmarshal(res, fg) + info := ItemFLIPGroup{} + + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return fg, nil + return &info, nil } diff --git a/pkg/cloudapi/flipgroup/list.go b/pkg/cloudapi/flipgroup/list.go index 1add550..cf5fa04 100644 --- a/pkg/cloudapi/flipgroup/list.go +++ b/pkg/cloudapi/flipgroup/list.go @@ -6,22 +6,32 @@ import ( "net/http" ) +// Request struct for get list FLIPGroup available to the current user type ListRequest struct { + // Page number + // Required: false Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false Size uint64 `url:"size,omitempty"` } -func (f FlipGroup) List(ctx context.Context, req ListRequest) (FlipGroupList, error) { +// List gets list FLIPGroup managed cluster instances available to the current user +func (f FLIPGroup) List(ctx context.Context, req ListRequest) (ListFLIPGroups, error) { url := "/cloudapi/flipgroup/list" - fgListRaw, err := f.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := f.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - fgList := FlipGroupList{} - if err := json.Unmarshal(fgListRaw, &fgList); err != nil { + list := ListFLIPGroups{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return fgList, nil + return list, nil } diff --git a/pkg/cloudapi/flipgroup/models.go b/pkg/cloudapi/flipgroup/models.go index 097d4eb..f2c76bf 100644 --- a/pkg/cloudapi/flipgroup/models.go +++ b/pkg/cloudapi/flipgroup/models.go @@ -1,40 +1,103 @@ package flipgroup -type FlipGroupRecord struct { +// Main information about FLIPGroup +type RecordFLIPGroup struct { + // Default GW DefaultGW string `json:"defaultGW"` - ID uint64 `json:"id"` - IP string `json:"ip"` - Name string `json:"name"` - Netmask uint64 `json:"netmask"` + + // ID + ID uint64 `json:"id"` + + // IP + IP string `json:"ip"` + + // Name + Name string `json:"name"` + + // Network mask + NetMask uint64 `json:"netmask"` } -type FlipGroupItem struct { - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - ClientIDs []uint64 `json:"clientIds"` - ClientType string `json:"clientType"` - ConnID uint64 `json:"connId"` - ConnType string `json:"connType"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DefaultGW string `json:"defaultGW"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - Description string `json:"desc"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - IP string `json:"ip"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - NetID uint64 `json:"netId"` - NetType string `json:"netType"` - Network string `json:"network"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - Status string `json:"status"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` +// Detailed information about FLIPGroup +type ItemFLIPGroup struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // List of client IDs + ClientIDs []uint64 `json:"clientIds"` + + // Client type + ClientType string `json:"clientType"` + + // Connection ID + ConnID uint64 `json:"connId"` + + // Connection type + ConnType string `json:"connType"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Default GW + DefaultGW string `json:"defaultGW"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // IP + IP string `json:"ip"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Network ID + NetID uint64 `json:"netId"` + + // Network type + NetType string `json:"netType"` + + // Network + Network string `json:"network"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Status + Status string `json:"status"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` } -type FlipGroupList []FlipGroupItem +// List of FLIPGroup +type ListFLIPGroups []ItemFLIPGroup diff --git a/pkg/cloudapi/image.go b/pkg/cloudapi/image.go index 3ee7c12..2f713b3 100644 --- a/pkg/cloudapi/image.go +++ b/pkg/cloudapi/image.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudapi/image" ) -func (ca *CloudApi) Image() *image.Image { +// Accessing the Image method group +func (ca *CloudAPI) Image() *image.Image { return image.New(ca.client) } diff --git a/pkg/cloudapi/image/create.go b/pkg/cloudapi/image/create.go index 628d7af..bca6c80 100644 --- a/pkg/cloudapi/image/create.go +++ b/pkg/cloudapi/image/create.go @@ -9,39 +9,90 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for create image type CreateRequest struct { - Name string `url:"name"` - URL string `url:"url"` - GID uint64 `url:"gid"` - BootType string `url:"boottype"` - ImageType string `url:"imagetype"` - Hotresize bool `url:"hotresize,omitempty"` - Username string `url:"username,omitempty"` - Password string `url:"password,omitempty"` - AccountID uint64 `url:"accountId,omitempty"` - UsernameDL string `url:"usernameDL,omitempty"` - PasswordDL string `url:"passwordDL,omitempty"` - SepID uint64 `url:"sepId,omitempty"` - Pool string `url:"poolName,omitempty"` - Architecture string `url:"architecture,omitempty"` - Drivers []string `url:"drivers"` + // Name of the rescue disk + // Required: true + Name string `url:"name"` + + // URL where to download media from + // Required: true + URL string `url:"url"` + + // Grid (platform) ID where this template should be create in + // Required: true + GID uint64 `url:"gid"` + + // Boot type of image bios or UEFI + // Required: true + BootType string `url:"boottype"` + + // Image type + // Should be: + // - linux + // - windows + // - or other + // Required: true + ImageType string `url:"imagetype"` + + // Does this machine supports hot resize + // Required: false + HotResize bool `url:"hotresize,omitempty"` + + // Optional username for the image + // Required: false + Username string `url:"username,omitempty"` + + // Optional password for the image + // Required: false + Password string `url:"password,omitempty"` + + // Account ID to make the image exclusive + // Required: false + AccountID uint64 `url:"accountId,omitempty"` + + // Username for upload binary media + // Required: false + UsernameDL string `url:"usernameDL,omitempty"` + + // Password for upload binary media + // Required: false + PasswordDL string `url:"passwordDL,omitempty"` + + // Storage endpoint provider ID + // Required: false + SEPID uint64 `url:"sepId,omitempty"` + + // Pool for image create + // Required: false + Pool string `url:"poolName,omitempty"` + + // Binary architecture of this image + // Should be: + // - X86_64 + // - PPC64_LE + // Required: false + Architecture string `url:"architecture,omitempty"` + + // List of types of compute suitable for image + // Example: [ "KVM_X86" ] + // Required: true + Drivers []string `url:"drivers"` } -func (irq CreateRequest) Validate() error { +func (irq CreateRequest) validate() error { if irq.Name == "" { return errors.New("validation-error: field Name can not be empty") } if irq.URL == "" { return errors.New("validation-error: field URL can not be empty") } - if irq.GID == 0 { return errors.New("validation-error: field GID can not be empty or equal to 0") } if irq.BootType == "" { return errors.New("validation-error: field BootType can not be empty") } - validate := validators.StringInSlice(irq.BootType, []string{"bios", "uefi"}) if !validate { return errors.New("validation-error: field BootType can be bios or uefi") @@ -49,16 +100,13 @@ func (irq CreateRequest) Validate() error { if irq.ImageType == "" { return errors.New("validation-error: field ImageType can not be empty") } - validate = validators.StringInSlice(irq.ImageType, []string{"windows", "linux", "other"}) if !validate { return errors.New("validation-error: field ImageType can be windows, linux or other") } - if len(irq.Drivers) == 0 || len(irq.Drivers) > 1 { return errors.New("validation-error: field Drivers can not be empty or have 2 or more elements") } - for _, v := range irq.Drivers { validate := validators.StringInSlice(v, []string{"KVM_X86"}) if !validate { @@ -69,8 +117,9 @@ func (irq CreateRequest) Validate() error { return nil } +// Create creates image from a media identified by URL func (i Image) Create(ctx context.Context, req CreateRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } @@ -88,5 +137,4 @@ func (i Image) Create(ctx context.Context, req CreateRequest) (uint64, error) { } return result, nil - } diff --git a/pkg/cloudapi/image/create_virtual.go b/pkg/cloudapi/image/create_virtual.go index d11c1bc..e11d01f 100644 --- a/pkg/cloudapi/image/create_virtual.go +++ b/pkg/cloudapi/image/create_virtual.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for create virtual image type CreateVirtualRequest struct { - Name string `url:"name"` + // Name of the virtual image to create + // Required: true + Name string `url:"name"` + + // ID of real image to link this virtual image to upon creation + // Required: true TargetID uint64 `url:"targetId"` } -func (irq CreateVirtualRequest) Validate() error { +func (irq CreateVirtualRequest) validate() error { if irq.Name == "" { return errors.New("validation-error: field Name can not be empty") } - if irq.TargetID == 0 { return errors.New("validation-error: field TargetID can not be empty or equal to 0") } @@ -24,8 +29,9 @@ func (irq CreateVirtualRequest) Validate() error { return nil } +// CreateVirtual creates virtual image func (i Image) CreateVirtual(ctx context.Context, req CreateVirtualRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } @@ -43,5 +49,4 @@ func (i Image) CreateVirtual(ctx context.Context, req CreateVirtualRequest) (uin } return result, nil - } diff --git a/pkg/cloudapi/image/delete.go b/pkg/cloudapi/image/delete.go index e09a426..71ce748 100644 --- a/pkg/cloudapi/image/delete.go +++ b/pkg/cloudapi/image/delete.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for delete image type DeleteRequest struct { - ImageID uint64 `url:"imageId"` - Permanently bool `url:"permanently"` + // ID of the image to delete + // Required: true + ImageID uint64 `url:"imageId"` + + // Whether to completely delete the image + // Required: false + Permanently bool `url:"permanently,omitempty"` } -func (irq DeleteRequest) Validate() error { +func (irq DeleteRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID can not be empty or equal to 0") } @@ -20,8 +26,9 @@ func (irq DeleteRequest) Validate() error { return nil } +// Delete deletes image by ID func (i Image) Delete(ctx context.Context, req DeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -39,5 +46,4 @@ func (i Image) Delete(ctx context.Context, req DeleteRequest) (bool, error) { } return result, nil - } diff --git a/pkg/cloudapi/image/get.go b/pkg/cloudapi/image/get.go index b1a6681..80852b4 100644 --- a/pkg/cloudapi/image/get.go +++ b/pkg/cloudapi/image/get.go @@ -7,12 +7,18 @@ import ( "net/http" ) +// Request struct for get detailed information about image type GetRequest struct { + // ID of image to get + // Required: true ImageID uint64 `url:"imageId"` - ShowAll bool `url:"show_all,omitempty"` + + // If set to False returns only images in status CREATED + // Required: false + ShowAll bool `url:"show_all,omitempty"` } -func (irq GetRequest) Validate() error { +func (irq GetRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID can not be empty or equal to 0") } @@ -20,8 +26,10 @@ func (irq GetRequest) Validate() error { return nil } -func (i Image) Get(ctx context.Context, req GetRequest) (*ImageExtend, error) { - err := req.Validate() +// Get gets image by ID. +// Returns image if user has rights on it +func (i Image) Get(ctx context.Context, req GetRequest) (*RecordImage, error) { + err := req.validate() if err != nil { return nil, err } @@ -33,12 +41,12 @@ func (i Image) Get(ctx context.Context, req GetRequest) (*ImageExtend, error) { return nil, err } - imageInfo := &ImageExtend{} + info := RecordImage{} - err = json.Unmarshal(res, imageInfo) + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return imageInfo, nil + return &info, nil } diff --git a/pkg/cloudapi/image/image.go b/pkg/cloudapi/image/image.go index d4221d2..b09f5c8 100644 --- a/pkg/cloudapi/image/image.go +++ b/pkg/cloudapi/image/image.go @@ -1,13 +1,16 @@ +// Lists all the images. A image is a template which can be used to deploy machines package image import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to image type Image struct { client interfaces.Caller } +// Builder for image endpoints func New(client interfaces.Caller) *Image { return &Image{ client, diff --git a/pkg/cloudapi/image/link.go b/pkg/cloudapi/image/link.go index fb256cf..45edb6b 100644 --- a/pkg/cloudapi/image/link.go +++ b/pkg/cloudapi/image/link.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for link virtual image to another image type LinkRequest struct { - ImageID uint64 `url:"imageId"` + // ID of the virtual image + // Required: true + ImageID uint64 `url:"imageId"` + + // ID of real image to link this virtual image to + // Required: true TargetID uint64 `url:"targetId"` } -func (irq LinkRequest) Validate() error { +func (irq LinkRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID can not be empty or equal to 0") } @@ -23,8 +29,9 @@ func (irq LinkRequest) Validate() error { return nil } +// Link links virtual image to another image in the platform func (i Image) Link(ctx context.Context, req LinkRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -42,5 +49,4 @@ func (i Image) Link(ctx context.Context, req LinkRequest) (bool, error) { } return result, nil - } diff --git a/pkg/cloudapi/image/list.go b/pkg/cloudapi/image/list.go index 9cdfe79..8833c7c 100644 --- a/pkg/cloudapi/image/list.go +++ b/pkg/cloudapi/image/list.go @@ -6,14 +6,23 @@ import ( "net/http" ) +// Request struct for get list available images type ListRequest struct { - AccountID uint64 `json:"accountId"` - Page uint64 `json:"page"` - Size uint64 `json:"size"` -} + // Optional account ID to include account images + // Required: false + AccountID uint64 `json:"accountId,omitempty"` + + // Page number + // Required: false + Page uint64 `json:"page,omitempty"` -func (i Image) List(ctx context.Context, req ListRequest) (ImageList, error) { + // Page size + // Required: false + Size uint64 `json:"size,omitempty"` +} +// List gets list available images, optionally filtering by account ID +func (i Image) List(ctx context.Context, req ListRequest) (ListImages, error) { url := "/cloudapi/image/list" res, err := i.client.DecortApiCall(ctx, http.MethodPost, url, req) @@ -21,12 +30,12 @@ func (i Image) List(ctx context.Context, req ListRequest) (ImageList, error) { return nil, err } - imageList := ImageList{} + list := ListImages{} - err = json.Unmarshal(res, &imageList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return imageList, nil + return list, nil } diff --git a/pkg/cloudapi/image/models.go b/pkg/cloudapi/image/models.go index 2b03a25..6f9d780 100644 --- a/pkg/cloudapi/image/models.go +++ b/pkg/cloudapi/image/models.go @@ -1,68 +1,181 @@ package image -type ImageRecord struct { - AccountID uint64 `json:"accountId"` - Architecture string `json:"architecture"` - BootType string `json:"bootType"` - Bootable bool `json:"bootable"` - CDROM bool `json:"cdrom"` - Description string `json:"desc"` - Drivers []string `json:"drivers"` - HotResize bool `json:"hotResize"` - ID uint64 `json:"id"` - LinkTo uint64 `json:"linkTo"` - Name string `json:"name"` - Pool string `json:"pool"` - SepID uint64 `json:"sepId"` - Size uint64 `json:"size"` - Status string `json:"status"` - Type string `json:"type"` - Username string `json:"username"` - Virtual bool `json:"virtual"` +// Main information about image +type ItemImage struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Architecture + Architecture string `json:"architecture"` + + // Boot type + BootType string `json:"bootType"` + + // Bootable + Bootable bool `json:"bootable"` + + // CDROM + CDROM bool `json:"cdrom"` + + // Description + Description string `json:"desc"` + + // List drivers + Drivers []string `json:"drivers"` + + // HotResize + HotResize bool `json:"hotResize"` + + // ID + ID uint64 `json:"id"` + + // Link to + LinkTo uint64 `json:"linkTo"` + + // Name + Name string `json:"name"` + + // Pool + Pool string `json:"pool"` + + // SepID + SepID uint64 `json:"sepId"` + + // Size + Size uint64 `json:"size"` + + // Status + Status string `json:"status"` + + // Type + Type string `json:"type"` + + // Username + Username string `json:"username"` + + // Virtual + Virtual bool `json:"virtual"` } -type ImageList []ImageRecord +// List of information about images +type ListImages []ItemImage +// History type History struct { - GUID string `json:"guid"` - ID uint64 `json:"id"` + // GUID + GUID string `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Timestamp Timestamp uint64 `json:"timestamp"` } -type ImageExtend struct { - UNCPath string `json:"UNCPath"` - CKey string `json:"_ckey"` - AccountID uint64 `json:"accountId"` - ACL interface{} `json:"acl"` - Architecture string `json:"architecture"` - BootType string `json:"bootType"` - Bootable bool `json:"bootable"` - ComputeCiID uint64 `json:"computeciId"` - DeletedTime uint64 `json:"deletedTime"` - Description string `json:"desc"` - Drivers []string `json:"drivers"` - Enabled bool `json:"enabled"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - History []History `json:"history"` - HotResize bool `json:"hotResize"` - ID uint64 `json:"id"` - LastModified uint64 `json:"lastModified"` - LinkTo uint64 `json:"linkTo"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - Password string `json:"password"` - Pool string `json:"pool"` - ProviderName string `json:"provider_name"` - PurgeAttempts uint64 `json:"purgeAttempts"` - ResID string `json:"resId"` - RescueCD bool `json:"rescuecd"` - SepID uint64 `json:"sepId"` - SharedWith []uint64 `json:"sharedWith"` - Size uint64 `json:"size"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - Type string `json:"type"` - Username string `json:"username"` - Version string `json:"version"` +// Detailed information about image +type RecordImage struct { + // UNCPathj + UNCPath string `json:"UNCPath"` + + // CKey + CKey string `json:"_ckey"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Access Control List + ACL interface{} `json:"acl"` + + // Architecture + Architecture string `json:"architecture"` + + // Boot type + BootType string `json:"bootType"` + + // Bootable + Bootable bool `json:"bootable"` + + // ComputeCI ID + ComputeCIID uint64 `json:"computeciId"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // List of drivers + Drivers []string `json:"drivers"` + + // Enabled + Enabled bool `json:"enabled"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // History + History []History `json:"history"` + + // HotResize + HotResize bool `json:"hotResize"` + + // ID + ID uint64 `json:"id"` + + // Last modified + LastModified uint64 `json:"lastModified"` + + // Link to + LinkTo uint64 `json:"linkTo"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Password + Password string `json:"password"` + + // Pool + Pool string `json:"pool"` + + // ProviderName + ProviderName string `json:"provider_name"` + + // Purge attempts + PurgeAttempts uint64 `json:"purgeAttempts"` + + // Resource ID + ResID string `json:"resId"` + + // RescueCD + RescueCD bool `json:"rescuecd"` + + // SepID + SepID uint64 `json:"sepId"` + + // SharedWith list + SharedWith []uint64 `json:"sharedWith"` + + // Size + Size uint64 `json:"size"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Type + Type string `json:"type"` + + // Username + Username string `json:"username"` + + // Version + Version string `json:"version"` } diff --git a/pkg/cloudapi/image/rename.go b/pkg/cloudapi/image/rename.go index 918e75b..f45d8c7 100644 --- a/pkg/cloudapi/image/rename.go +++ b/pkg/cloudapi/image/rename.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for rename image type RenameRequest struct { + // ID of the virtual image to rename + // Required: true ImageID uint64 `url:"imageId"` - Name string `url:"name"` + + // New name + // Required: true + Name string `url:"name"` } -func (irq RenameRequest) Validate() error { +func (irq RenameRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID can not be empty or equal to 0") } - if irq.Name == "" { return errors.New("validation-error: field Name can not be empty") } @@ -24,8 +29,9 @@ func (irq RenameRequest) Validate() error { return nil } +// Rename renames image func (i Image) Rename(ctx context.Context, req RenameRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -43,5 +49,4 @@ func (i Image) Rename(ctx context.Context, req RenameRequest) (bool, error) { } return result, nil - } diff --git a/pkg/cloudapi/k8ci.go b/pkg/cloudapi/k8ci.go index b452b28..4a7ec88 100644 --- a/pkg/cloudapi/k8ci.go +++ b/pkg/cloudapi/k8ci.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudapi/k8ci" ) -func (ca *CloudApi) K8CI() *k8ci.K8CI { +// Accessing the K8CI method group +func (ca *CloudAPI) K8CI() *k8ci.K8CI { return k8ci.New(ca.client) } diff --git a/pkg/cloudapi/k8ci/get.go b/pkg/cloudapi/k8ci/get.go index 3fc1eb1..d2be55f 100644 --- a/pkg/cloudapi/k8ci/get.go +++ b/pkg/cloudapi/k8ci/get.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get information about K8CI type GetRequest struct { + // ID of the K8 catalog item to get + // Required: true K8CIID uint64 `url:"k8ciId"` } -func (krq GetRequest) Validate() error { +func (krq GetRequest) validate() error { if krq.K8CIID == 0 { return errors.New("field K8CIID can not be empty or equal to 0") } @@ -19,21 +22,24 @@ func (krq GetRequest) Validate() error { return nil } -func (k K8CI) Get(ctx context.Context, req GetRequest) (*K8CIRecord, error) { - if err := req.Validate(); err != nil { +// Get gets details of the specified K8 catalog item +func (k K8CI) Get(ctx context.Context, req GetRequest) (*RecordK8CI, error) { + if err := req.validate(); err != nil { return nil, err } url := "/cloudapi/k8ci/get" - k8ciRaw, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - k8ci := &K8CIRecord{} - if err := json.Unmarshal(k8ciRaw, k8ci); err != nil { + info := RecordK8CI{} + err = json.Unmarshal(res, &info) + if err != nil { return nil, err } - return k8ci, nil + return &info, nil } diff --git a/pkg/cloudapi/k8ci/k8ci.go b/pkg/cloudapi/k8ci/k8ci.go index 25cfd8f..fdd2eab 100644 --- a/pkg/cloudapi/k8ci/k8ci.go +++ b/pkg/cloudapi/k8ci/k8ci.go @@ -1,13 +1,16 @@ +// API to manage K8CI instances package k8ci import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to K8CI type K8CI struct { client interfaces.Caller } +// Builder for K8CI endpoints func New(client interfaces.Caller) *K8CI { return &K8CI{ client, diff --git a/pkg/cloudapi/k8ci/list.go b/pkg/cloudapi/k8ci/list.go index c80a0c1..4596929 100644 --- a/pkg/cloudapi/k8ci/list.go +++ b/pkg/cloudapi/k8ci/list.go @@ -6,23 +6,36 @@ import ( "net/http" ) +// Request struct for get list information about images type ListRequest struct { - IncludeDisabled bool `url:"includeDisabled,omitempty"` - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` + // List disabled items as well + // Required: false + IncludeDisabled bool `url:"includeDisabled,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (k K8CI) List(ctx context.Context, req ListRequest) (K8CIList, error) { +// List gets list all k8ci catalog items available to the current user +func (k K8CI) List(ctx context.Context, req ListRequest) (ListK8CI, error) { url := "/cloudapi/k8ci/list" - k8ciListRaw, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - k8ciList := K8CIList{} - if err := json.Unmarshal(k8ciListRaw, &k8ciList); err != nil { + list := ListK8CI{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return k8ciList, nil + return list, nil } diff --git a/pkg/cloudapi/k8ci/list_deleted.go b/pkg/cloudapi/k8ci/list_deleted.go index 4b00f62..e0981ab 100644 --- a/pkg/cloudapi/k8ci/list_deleted.go +++ b/pkg/cloudapi/k8ci/list_deleted.go @@ -6,22 +6,32 @@ import ( "net/http" ) +// Request struct for get list information about deleted images type ListDeletedRequest struct { + // Page number + // Required: false Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false Size uint64 `url:"size,omitempty"` } -func (k K8CI) ListDeleted(ctx context.Context, req ListDeletedRequest) (K8CIList, error) { +// ListDeleted gets list all deleted k8ci catalog items available to the current user +func (k K8CI) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListK8CI, error) { url := "/cloudapi/k8ci/listDeleted" - k8ciListRaw, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - k8ciList := K8CIList{} - if err := json.Unmarshal(k8ciListRaw, &k8ciList); err != nil { + list := ListK8CI{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return k8ciList, nil + return list, nil } diff --git a/pkg/cloudapi/k8ci/models.go b/pkg/cloudapi/k8ci/models.go index 34a7567..88f3776 100644 --- a/pkg/cloudapi/k8ci/models.go +++ b/pkg/cloudapi/k8ci/models.go @@ -1,15 +1,28 @@ package k8ci -type K8CIItem struct { +// Detailed information about K8CI +type ItemK8CI struct { + // Created time CreatedTime uint64 `json:"createdTime"` - K8CIRecord + + // Main information about K8CI + RecordK8CI } -type K8CIList []K8CIItem +// List of K8CI +type ListK8CI []ItemK8CI -type K8CIRecord struct { +// Main information about K8CI +type RecordK8CI struct { + // Description Description string `json:"desc"` - ID uint64 `json:"id"` - Name string `json:"name"` - Version string `json:"version"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Version + Version string `json:"version"` } diff --git a/pkg/cloudapi/k8s.go b/pkg/cloudapi/k8s.go index 9f322d7..1f5d060 100644 --- a/pkg/cloudapi/k8s.go +++ b/pkg/cloudapi/k8s.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudapi/k8s" ) -func (ca *CloudApi) K8S() *k8s.K8S { +// Accessing the K8S method group +func (ca *CloudAPI) K8S() *k8s.K8S { return k8s.New(ca.client) } diff --git a/pkg/cloudapi/k8s/create.go b/pkg/cloudapi/k8s/create.go index 846a663..8cb2a81 100644 --- a/pkg/cloudapi/k8s/create.go +++ b/pkg/cloudapi/k8s/create.go @@ -7,28 +7,86 @@ import ( "strings" ) +// Request struct for create kubernetes cluster type CreateRequest struct { - Name string `url:"name"` - RGID uint64 `url:"rgId"` - K8SCIID uint64 `url:"k8ciId"` - WorkerGroupName string `url:"workerGroupName"` - Labels []string `url:"labels,omitempty"` - Taints []string `url:"taints,omitempty"` - Annotations []string `url:"annotations,omitempty"` - MasterNum uint `url:"masterNum,omitempty"` - MasterCPU uint `url:"masterCPU,omitempty"` - MasterRAM uint `url:"masterRam,omitempty"` - MasterDisk uint `url:"masterDisk,omitempty"` - WorkerNum uint `url:"workerNum,omitempty"` - WorkerCPU uint `url:"workerCPU,omitempty"` - WorkerRAM uint `url:"workerRam,omitempty"` - WorkerDisk uint `url:"workerDisk,omitempty"` - ExtNetID uint64 `url:"extnetId,omitempty"` - WithLB bool `url:"withLB,omitempty"` - Description string `url:"desc, omitempty"` + // Name of Kubernetes cluster + // Required: true + Name string `url:"name"` + + // Resource Group ID for cluster placement + // Required: true + RGID uint64 `url:"rgId"` + + // ID of Kubernetes catalog item (k8sci) for cluster + // Required: true + K8SCIID uint64 `url:"k8ciId"` + + // Name for first worker group created with cluster + // Required: true + WorkerGroupName string `url:"workerGroupName"` + + // List of strings with labels for default worker group + // i.e: ["label1=value1", "label2=value2"] + // Required: false + Labels []string `url:"labels,omitempty"` + + // List of strings with taints for default worker group + // i.e: ["key1=value1:NoSchedule", "key2=value2:NoExecute"] + // Required: false + Taints []string `url:"taints,omitempty"` + + // List of strings with annotations for worker group + // i.e: ["key1=value1", "key2=value2"] + // Required: false + Annotations []string `url:"annotations,omitempty"` + + // Number of master nodes to create + // Required: false + MasterNum uint `url:"masterNum,omitempty"` + + // Master node CPU count + // Required: false + MasterCPU uint `url:"masterCPU,omitempty"` + + // Master node RAM volume in MB + // Required: false + MasterRAM uint `url:"masterRam,omitempty"` + + // Master node boot disk size in GB If 0 is specified, size is defined by the OS image size + // Required: false + MasterDisk uint `url:"masterDisk,omitempty"` + + // Number of worker nodes to create in default worker group + // Required: false + WorkerNum uint `url:"workerNum,omitempty"` + + // Worker node CPU count + // Required: false + WorkerCPU uint `url:"workerCPU,omitempty"` + + // Worker node RAM volume in MB + // Required: false + WorkerRAM uint `url:"workerRam,omitempty"` + + // Worker node boot disk size in GB. If 0 is specified, size is defined by the OS image size + // Required: false + WorkerDisk uint `url:"workerDisk,omitempty"` + + // ID of the external network to connect load balancer and cluster ViNS. If 0 is specified, external network selects automatically to + // Required: false + ExtNetID uint64 `url:"extnetId,omitempty"` + + // Create Kubernetes cluster with masters nodes behind load balancer if true. + // Otherwise give all cluster nodes direct external addresses from selected ExtNet + // Required: false + WithLB bool `url:"withLB,omitempty"` + + // Text description of this Kubernetes cluster + // Required: false + Description string `url:"desc, omitempty"` } -func (krq CreateRequest) Validate() error { +func (krq CreateRequest) validate() error { if krq.Name == "" { return errors.New("validation-error: field Name can not be empty") } @@ -38,7 +96,6 @@ func (krq CreateRequest) Validate() error { if krq.K8SCIID == 0 { return errors.New("validation-error: field K8SCIID can not be empty or equal to 0") } - if krq.WorkerGroupName == "" { return errors.New("validation-error: field WorkerGroupName can not be empty") } @@ -46,8 +103,9 @@ func (krq CreateRequest) Validate() error { return nil } +// Create creates a new Kubernetes cluster in the specified Resource Group func (k8s K8S) Create(ctx context.Context, req CreateRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } @@ -59,6 +117,7 @@ func (k8s K8S) Create(ctx context.Context, req CreateRequest) (string, error) { return "", err } - return strings.ReplaceAll(string(res), "\"", ""), nil + result := strings.ReplaceAll(string(res), "\"", "") + return result, nil } diff --git a/pkg/cloudapi/k8s/delete.go b/pkg/cloudapi/k8s/delete.go index fc2d42f..691a8af 100644 --- a/pkg/cloudapi/k8s/delete.go +++ b/pkg/cloudapi/k8s/delete.go @@ -7,12 +7,19 @@ import ( "strconv" ) +// Request struct for delete kubernetes cluster type DeleteRequest struct { - K8SID uint64 `url:"k8sId"` - Permanently bool `url:"permanently"` + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // True if cluster is destroyed permanently. + // Otherwise it can be restored from Recycle Bin + // Required: true + Permanently bool `url:"permanently"` } -func (krq DeleteRequest) Validate() error { +func (krq DeleteRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } @@ -20,8 +27,9 @@ func (krq DeleteRequest) Validate() error { return nil } +// Delete deletes kubernetes cluster func (k8s K8S) Delete(ctx context.Context, req DeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -37,5 +45,6 @@ func (k8s K8S) Delete(ctx context.Context, req DeleteRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/k8s/delete_master_from_group.go b/pkg/cloudapi/k8s/delete_master_from_group.go index 3401fc9..9df0b4d 100644 --- a/pkg/cloudapi/k8s/delete_master_from_group.go +++ b/pkg/cloudapi/k8s/delete_master_from_group.go @@ -7,20 +7,28 @@ import ( "strconv" ) +// Request struct for delete master from group type DeleteMasterFromGroupRequest struct { - K8SID uint64 `url:"k8sId"` - MasterGroupID uint64 `url:"masterGroupId"` - MasterIDs []string `url:"masterIds"` + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // ID of the masters compute group + // Required: true + MasterGroupID uint64 `url:"masterGroupId"` + + // List of Compute IDs of master nodes to delete + // Required: true + MasterIDs []string `url:"masterIds"` } -func (krq DeleteMasterFromGroupRequest) Validate() error { +func (krq DeleteMasterFromGroupRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } if krq.MasterGroupID == 0 { return errors.New("validation-error: field MasterGroupID can not be empty or equal to 0") } - if len(krq.MasterIDs) == 0 { return errors.New("validation-error: field MasterIDs can not be empty") } @@ -28,8 +36,9 @@ func (krq DeleteMasterFromGroupRequest) Validate() error { return nil } +// DeleteMasterFromGroup deletes compute from masters group in selected Kubernetes cluster func (k8s K8S) DeleteMasterFromGroup(ctx context.Context, req DeleteMasterFromGroupRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -45,5 +54,6 @@ func (k8s K8S) DeleteMasterFromGroup(ctx context.Context, req DeleteMasterFromGr if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/k8s/delete_worker_from_group.go b/pkg/cloudapi/k8s/delete_worker_from_group.go index 020ea3d..e6f3efb 100644 --- a/pkg/cloudapi/k8s/delete_worker_from_group.go +++ b/pkg/cloudapi/k8s/delete_worker_from_group.go @@ -7,20 +7,28 @@ import ( "strconv" ) +// Request struct for delete worker from group type DeleteWorkerFromGroupRequest struct { - K8SID uint64 `url:"k8sId"` + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // ID of the workers compute group + // Required: true WorkersGroupID uint64 `url:"workersGroupId"` - WorkerID uint64 `url:"workerId"` + + // Compute ID of worker node to delete + // Required: true + WorkerID uint64 `url:"workerId"` } -func (krq DeleteWorkerFromGroupRequest) Validate() error { +func (krq DeleteWorkerFromGroupRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } if krq.WorkersGroupID == 0 { return errors.New("validation-error: field WorkersGroupID can not be empty or equal to 0") } - if krq.WorkerID == 0 { return errors.New("validation-error: field WorkerID can not be empty or equal to 0") } @@ -28,8 +36,9 @@ func (krq DeleteWorkerFromGroupRequest) Validate() error { return nil } +// DeleteWorkerFromGroup deletes worker compute from workers group in selected Kubernetes cluster func (k8s K8S) DeleteWorkerFromGroup(ctx context.Context, req DeleteWorkerFromGroupRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -45,5 +54,6 @@ func (k8s K8S) DeleteWorkerFromGroup(ctx context.Context, req DeleteWorkerFromGr if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/k8s/disable_enable.go b/pkg/cloudapi/k8s/disable_enable.go index c13207c..f74cdb2 100644 --- a/pkg/cloudapi/k8s/disable_enable.go +++ b/pkg/cloudapi/k8s/disable_enable.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for disable/enable kubernetes cluster type DisabelEnableRequest struct { + // Kubernetes cluster ID + // Required: true K8SID uint64 `url:"k8sId"` } -func (krq DisabelEnableRequest) Validate() error { +func (krq DisabelEnableRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (krq DisabelEnableRequest) Validate() error { return nil } +// Disable disables kubernetes cluster by ID func (k8s K8S) Disable(ctx context.Context, req DisabelEnableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -36,11 +40,13 @@ func (k8s K8S) Disable(ctx context.Context, req DisabelEnableRequest) (bool, err if err != nil { return false, err } + return result, nil } +// Enable enables kubernetes cluster by ID func (k8s K8S) Enable(ctx context.Context, req DisabelEnableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -56,5 +62,6 @@ func (k8s K8S) Enable(ctx context.Context, req DisabelEnableRequest) (bool, erro if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/k8s/find_group_by_label.go b/pkg/cloudapi/k8s/find_group_by_label.go index 5ac5377..90bc818 100644 --- a/pkg/cloudapi/k8s/find_group_by_label.go +++ b/pkg/cloudapi/k8s/find_group_by_label.go @@ -7,17 +7,26 @@ import ( "net/http" ) +// Request struct for get information about group of kubernetes cluster type FindGroupByLabelRequest struct { - K8SID uint64 `url:"k8sId"` + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // List of labels to search + // Required: true Labels []string `url:"labels"` - Strict bool `url:"strict"` + + // If true and more than one label provided, select only groups that have all provided labels. + // If false - groups that have at least one label + // Required: true + Strict bool `url:"strict"` } -func (krq FindGroupByLabelRequest) Validate() error { +func (krq FindGroupByLabelRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } - if len(krq.Labels) == 0 { return errors.New("validation-error: field Labels can not be empty") } @@ -25,8 +34,9 @@ func (krq FindGroupByLabelRequest) Validate() error { return nil } -func (k8s K8S) FindGroupByLabel(ctx context.Context, req FindGroupByLabelRequest) (K8SGroupList, error) { - err := req.Validate() +// FindGroupByLabel find worker group information by one on more labels +func (k8s K8S) FindGroupByLabel(ctx context.Context, req FindGroupByLabelRequest) (ListK8SGroups, error) { + err := req.validate() if err != nil { return nil, err } @@ -38,12 +48,12 @@ func (k8s K8S) FindGroupByLabel(ctx context.Context, req FindGroupByLabelRequest return nil, err } - k8sGroupList := K8SGroupList{} + list := ListK8SGroups{} - err = json.Unmarshal(res, &k8sGroupList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return k8sGroupList, nil + return list, nil } diff --git a/pkg/cloudapi/k8s/get.go b/pkg/cloudapi/k8s/get.go index c12325c..882ab88 100644 --- a/pkg/cloudapi/k8s/get.go +++ b/pkg/cloudapi/k8s/get.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get detailed information about kubernetes cluster type GetRequest struct { + // Kubernetes cluster ID + // Required: true K8SID uint64 `url:"k8sId"` } -func (krq GetRequest) Validate() error { +func (krq GetRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (krq GetRequest) Validate() error { return nil } -func (k8s K8S) Get(ctx context.Context, req GetRequest) (*K8SRecord, error) { - err := req.Validate() +// Get gets information about Kubernetes cluster +func (k8s K8S) Get(ctx context.Context, req GetRequest) (*RecordK8S, error) { + err := req.validate() if err != nil { return nil, err } @@ -32,12 +36,12 @@ func (k8s K8S) Get(ctx context.Context, req GetRequest) (*K8SRecord, error) { return nil, err } - k8sInfo := &K8SRecord{} + info := RecordK8S{} - err = json.Unmarshal(res, k8sInfo) + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return k8sInfo, nil + return &info, nil } diff --git a/pkg/cloudapi/k8s/get_config.go b/pkg/cloudapi/k8s/get_config.go index 05a7c4e..24739b4 100644 --- a/pkg/cloudapi/k8s/get_config.go +++ b/pkg/cloudapi/k8s/get_config.go @@ -6,11 +6,14 @@ import ( "net/http" ) +// Request struct for get configuration of kubernetes cluster type GetConfigRequest struct { + // Kubernetes cluster ID + // Required: true K8SID uint64 `url:"k8sId"` } -func (krq GetConfigRequest) Validate() error { +func (krq GetConfigRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } @@ -18,8 +21,9 @@ func (krq GetConfigRequest) Validate() error { return nil } +// GetConfig gets configuration data to access Kubernetes cluster func (k8s K8S) GetConfig(ctx context.Context, req GetConfigRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } diff --git a/pkg/cloudapi/k8s/get_node_annotations.go b/pkg/cloudapi/k8s/get_node_annotations.go index 0e64434..8d557f7 100644 --- a/pkg/cloudapi/k8s/get_node_annotations.go +++ b/pkg/cloudapi/k8s/get_node_annotations.go @@ -6,12 +6,18 @@ import ( "net/http" ) +// Request struct for get node annotations type GetNodeAnnotationsRequest struct { - K8SID uint64 `url:"k8sId"` + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // Node ID + // Required: true NodeID uint64 `url:"nodeId"` } -func (krq GetNodeAnnotationsRequest) Validate() error { +func (krq GetNodeAnnotationsRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } @@ -22,8 +28,9 @@ func (krq GetNodeAnnotationsRequest) Validate() error { return nil } +// GetNodeAnnotations gets kubernetes cluster worker node annotations func (k8s K8S) GetNodeAnnotations(ctx context.Context, req GetNodeAnnotationsRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } diff --git a/pkg/cloudapi/k8s/get_node_taints.go b/pkg/cloudapi/k8s/get_node_taints.go index 4d3ff79..8d4a678 100644 --- a/pkg/cloudapi/k8s/get_node_taints.go +++ b/pkg/cloudapi/k8s/get_node_taints.go @@ -6,12 +6,18 @@ import ( "net/http" ) +// Request struct for get node taints type GetNodeTaintsRequest struct { - K8SID uint64 `url:"k8sId"` + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // Node ID + // Required: false NodeID uint64 `url:"nodeId"` } -func (krq GetNodeTaintsRequest) Validate() error { +func (krq GetNodeTaintsRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } @@ -22,8 +28,9 @@ func (krq GetNodeTaintsRequest) Validate() error { return nil } +// GetNodeTaints gets kubernetes cluster worker node taints func (k8s K8S) GetNodeTaints(ctx context.Context, req GetNodeTaintsRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } diff --git a/pkg/cloudapi/k8s/k8s.go b/pkg/cloudapi/k8s/k8s.go index 5ff017e..47d3cda 100644 --- a/pkg/cloudapi/k8s/k8s.go +++ b/pkg/cloudapi/k8s/k8s.go @@ -1,13 +1,16 @@ +// API for Kubernetes clusters management package k8s import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to K8S type K8S struct { client interfaces.Caller } +// Builder for K8S endpoints func New(client interfaces.Caller) *K8S { return &K8S{ client, diff --git a/pkg/cloudapi/k8s/list.go b/pkg/cloudapi/k8s/list.go index 2168358..f78d7a7 100644 --- a/pkg/cloudapi/k8s/list.go +++ b/pkg/cloudapi/k8s/list.go @@ -6,14 +6,23 @@ import ( "net/http" ) +// Request struct for get list information K8S type ListRequest struct { - IncludeDeleted bool `url:"includedeleted"` - Page uint64 `url:"page"` - Size uint64 `url:"size"` -} + // Include deleted clusters in result + // Required: false + IncludeDeleted bool `url:"includedeleted,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` -func (k8s K8S) List(ctx context.Context, req ListRequest) (K8SList, error) { + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} +// List gets list all kubernetes clusters the user has access to +func (k8s K8S) List(ctx context.Context, req ListRequest) (ListK8SClusters, error) { url := "/cloudapi/k8s/list" res, err := k8s.client.DecortApiCall(ctx, http.MethodPost, url, req) @@ -21,12 +30,12 @@ func (k8s K8S) List(ctx context.Context, req ListRequest) (K8SList, error) { return nil, err } - k8sList := K8SList{} + list := ListK8SClusters{} - err = json.Unmarshal(res, &k8sList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return k8sList, nil + return list, nil } diff --git a/pkg/cloudapi/k8s/list_deleted.go b/pkg/cloudapi/k8s/list_deleted.go index b56e4bd..594401c 100644 --- a/pkg/cloudapi/k8s/list_deleted.go +++ b/pkg/cloudapi/k8s/list_deleted.go @@ -6,13 +6,19 @@ import ( "net/http" ) +// Request struct for get list deleted kubernetes cluster type ListDeletedRequest struct { - Page uint64 `url:"page"` - Size uint64 `url:"size"` -} + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` -func (k8s K8S) ListDeleted(ctx context.Context, req ListDeletedRequest) (K8SList, error) { + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} +// ListDeleted gets all deleted kubernetes clusters the user has access to +func (k8s K8S) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListK8SClusters, error) { url := "/cloudapi/k8s/listDeleted" res, err := k8s.client.DecortApiCall(ctx, http.MethodPost, url, req) @@ -20,12 +26,12 @@ func (k8s K8S) ListDeleted(ctx context.Context, req ListDeletedRequest) (K8SList return nil, err } - k8sList := K8SList{} + list := ListK8SClusters{} - err = json.Unmarshal(res, &k8sList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return k8sList, nil + return list, nil } diff --git a/pkg/cloudapi/k8s/models.go b/pkg/cloudapi/k8s/models.go index c5e345b..2578149 100644 --- a/pkg/cloudapi/k8s/models.go +++ b/pkg/cloudapi/k8s/models.go @@ -1,119 +1,290 @@ package k8s -type K8SGroup struct { - Annotations []string `json:"annotations"` - CPU uint64 `json:"cpu"` - DetailedInfo DetailedInfoList `json:"detailedInfo"` - Disk uint64 `json:"disk"` - GUID string `json:"guid"` - ID uint64 `json:"id"` - Labels []string `json:"labels"` - Name string `json:"name"` - Num uint64 `json:"num"` - RAM uint64 `json:"ram"` - Taints []string `json:"taints"` +// Main information about kubernetes cluster +type ItemK8SGroup struct { + // List of Annotations + Annotations []string `json:"annotations"` + + // Number of CPU + CPU uint64 `json:"cpu"` + + // List detailed information + DetailedInfo ListDetailedInfo `json:"detailedInfo"` + + // Disk ID + Disk uint64 `json:"disk"` + + // GUID + GUID string `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // List of Labels + Labels []string `json:"labels"` + + // Name + Name string `json:"name"` + + // Num + Num uint64 `json:"num"` + + // Number of RAM + RAM uint64 `json:"ram"` + + // List of taints + Taints []string `json:"taints"` } -type K8SGroupList []K8SGroup +// List kubernetes cluster groups +type ListK8SGroups []ItemK8SGroup -type DetailedInfo struct { - ID uint64 `json:"id"` - Name string `json:"name"` - Status string `json:"status"` +// Detailed information +type ItemDetailedInfo struct { + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Status + Status string `json:"status"` + + // Tech status TechStatus string `json:"techStatus"` } -type DetailedInfoList []DetailedInfo - -type K8SRecord struct { - ACL ACLGroup `json:"ACL"` - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - BServiceID uint64 `json:"bserviceId"` - CIID uint64 `json:"ciId"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - ID uint64 `json:"id"` - K8CIName string `json:"k8ciName"` - K8SGroups K8SGroups `json:"k8sGroups"` - LBID uint64 `json:"lbId"` - Name string `json:"name"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` +// List detailed information +type ListDetailedInfo []ItemDetailedInfo + +// Deteal information about kubernetes cluster +type RecordK8S struct { + // Access Control List + ACL RecordACL `json:"ACL"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Basic Service ID + BServiceID uint64 `json:"bserviceId"` + + // CIID + CIID uint64 `json:"ciId"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // ID + ID uint64 `json:"id"` + + // K8CI name + K8CIName string `json:"k8ciName"` + + // Kubernetes cluster groups information + K8SGroups RecordK8SGroups `json:"k8sGroups"` + + // Load balancer ID + LBID uint64 `json:"lbId"` + + // Name + Name string `json:"name"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` } -type K8SGroups struct { - Masters MasterGroup `json:"masters"` - Workers K8SGroupList `json:"workers"` +// Detailed information about kubernetes cluster groups +type RecordK8SGroups struct { + + // Master information + Masters MasterGroup `json:"masters"` + + // Worker information + Workers ListK8SGroups `json:"workers"` } +// Master group information type MasterGroup struct { - CPU uint64 `json:"cpu"` - DetailedInfo DetailedInfoList `json:"detailedInfo"` - Disk uint64 `json:"disk"` - ID uint64 `json:"id"` - Name string `json:"name"` - Num uint64 `json:"num"` - RAM uint64 `json:"ram"` + // Number of CPU + CPU uint64 `json:"cpu"` + + // Detailed information + DetailedInfo ListDetailedInfo `json:"detailedInfo"` + + // Disk ID + Disk uint64 `json:"disk"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Num + Num uint64 `json:"num"` + + // Number of RAM + RAM uint64 `json:"ram"` } -type ACLGroup struct { - AccountACL ACLList `json:"accountAcl"` - K8SACL ACLList `json:"k8sAcl"` - RGACL ACLList `json:"rgAcl"` +// Access Control List +type RecordACL struct { + // Account ACL + AccountACL ListACL `json:"accountAcl"` + + // K8S ACL + K8SACL ListACL `json:"k8sAcl"` + + // RG ACL + RGACL ListACL `json:"rgAcl"` } -type ACL struct { - Explicit bool `json:"explicit"` - GUID string `json:"guid"` - Right string `json:"right"` - Status string `json:"status"` - Type string `json:"type"` +// Main information of Access Control List +type ItemACL struct { + // Explicit + Explicit bool `json:"explicit"` + + // GUID + GUID string `json:"guid"` + + // Right + Right string `json:"right"` + + // Status + Status string `json:"status"` + + // Type + Type string `json:"type"` + + // User group ID UserGroupID string `json:"userGroupId"` } -type ACLList []ACL - -type K8SItem struct { - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - ACL []interface{} `json:"acl"` - BServiceID uint64 `json:"bserviceId"` - CIID uint64 `json:"ciId"` - Config interface{} `json:"config"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - Description string `json:"desc"` - ExtNetID uint64 `json:"extnetId"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - LBID uint64 `json:"lbId"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - ServiceAccount ServiceAccount `json:"serviceAccount"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - VINSID uint64 `json:"vinsId"` - WorkersGroup K8SGroupList `json:"workersGroups"` +// List of ACL +type ListACL []ItemACL + +// Main information about kubernetes cluster +type ItemK8SCluster struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Access Control List + ACL []interface{} `json:"acl"` + + // Basic Service ID + BServiceID uint64 `json:"bserviceId"` + + // CIID + CIID uint64 `json:"ciId"` + + // Config + Config interface{} `json:"config"` + + // Create by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // External network ID + ExtNetID uint64 `json:"extnetId"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Load balancer ID + LBID uint64 `json:"lbId"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Information about service account + ServiceAccount RecordServiceAccount `json:"serviceAccount"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // VINS ID + VINSID uint64 `json:"vinsId"` + + // List workers group + WorkersGroup ListK8SGroups `json:"workersGroups"` } -type ServiceAccount struct { - GUID string `json:"guid"` +// Information about service account +type RecordServiceAccount struct { + // GUID + GUID string `json:"guid"` + + // Password Password string `json:"password"` + + // Username Username string `json:"username"` } -type K8SList []K8SItem +// List of kubernetes clusters +type ListK8SClusters []ItemK8SCluster diff --git a/pkg/cloudapi/k8s/restore.go b/pkg/cloudapi/k8s/restore.go index 3aea1d9..3ee848e 100644 --- a/pkg/cloudapi/k8s/restore.go +++ b/pkg/cloudapi/k8s/restore.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for restore kubernetes cluster type RestoreRequest struct { + // Kubernetes cluster ID + // Required: true K8SID uint64 `url:"k8sId"` } -func (krq RestoreRequest) Validate() error { +func (krq RestoreRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (krq RestoreRequest) Validate() error { return nil } +// Restore restore kubernetes cluster from Recycle Bin func (k8s K8S) Restore(ctx context.Context, req RestoreRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -36,5 +40,6 @@ func (k8s K8S) Restore(ctx context.Context, req RestoreRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/k8s/start.go b/pkg/cloudapi/k8s/start.go index 35f13cc..4021113 100644 --- a/pkg/cloudapi/k8s/start.go +++ b/pkg/cloudapi/k8s/start.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for start kubernetes cluster type StartRequest struct { + // Kubernetes cluster ID + // Required: true K8SID uint64 `url:"k8sId"` } -func (krq StartRequest) Validate() error { +func (krq StartRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (krq StartRequest) Validate() error { return nil } +// Start starts kubernetes cluster by ID func (k8s K8S) Start(ctx context.Context, req StartRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -36,5 +40,6 @@ func (k8s K8S) Start(ctx context.Context, req StartRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/k8s/stop.go b/pkg/cloudapi/k8s/stop.go index d124274..8f79558 100644 --- a/pkg/cloudapi/k8s/stop.go +++ b/pkg/cloudapi/k8s/stop.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for stop kubernetes cluster type StopRequest struct { + // Kubernetes cluster ID + // Required: true K8SID uint64 `url:"k8sId"` } -func (krq StopRequest) Validate() error { +func (krq StopRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (krq StopRequest) Validate() error { return nil } +// Stop stops kubernetes cluster by ID func (k8s K8S) Stop(ctx context.Context, req StopRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -36,5 +40,6 @@ func (k8s K8S) Stop(ctx context.Context, req StopRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/k8s/update.go b/pkg/cloudapi/k8s/update.go index a347cb9..7eb2106 100644 --- a/pkg/cloudapi/k8s/update.go +++ b/pkg/cloudapi/k8s/update.go @@ -7,13 +7,24 @@ import ( "strconv" ) +// Request struct for update kubernetes cluster type UpdateRequest struct { - K8SID uint64 `url:"k8sId"` - Name string `url:"name,omitempty"` + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // New name to set. + // If empty string is passed, name is not updated + // Required: false + Name string `url:"name,omitempty"` + + // New description to set. + // If empty string is passed, description is not updated + // Required: false Description string `url:"desc,omitempty"` } -func (krq UpdateRequest) Validate() error { +func (krq UpdateRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } @@ -21,8 +32,9 @@ func (krq UpdateRequest) Validate() error { return nil } +// Update updates name or description of Kubernetes cluster func (k8s K8S) Update(ctx context.Context, req UpdateRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -38,5 +50,6 @@ func (k8s K8S) Update(ctx context.Context, req UpdateRequest) (bool, error) { if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/k8s/worker_add.go b/pkg/cloudapi/k8s/worker_add.go index a787fc0..2c99c5b 100644 --- a/pkg/cloudapi/k8s/worker_add.go +++ b/pkg/cloudapi/k8s/worker_add.go @@ -7,21 +7,28 @@ import ( "strconv" ) +// Request struct for add worker to a kubernetes cluster type WorkerAddRequest struct { - K8SID uint64 `url:"k8sId"` + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // ID of the workers compute group + // Required: true WorkersGroupID uint64 `url:"workersGroupId"` - Num uint `url:"num"` + + // How many worker nodes to add + // Required: true + Num uint64 `url:"num"` } -func (krq WorkerAddRequest) Validate() error { +func (krq WorkerAddRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } - if krq.WorkersGroupID == 0 { return errors.New("validation-error: field WorkersGroupID can not be empty or equal to 0") } - if krq.Num == 0 { return errors.New("validation-error: field Num can not be empty or equal to 0") } @@ -29,8 +36,9 @@ func (krq WorkerAddRequest) Validate() error { return nil } +// WorkerAdd add worker nodes to a Kubernetes cluster func (k8s K8S) WorkerAdd(ctx context.Context, req WorkerAddRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -46,5 +54,6 @@ func (k8s K8S) WorkerAdd(ctx context.Context, req WorkerAddRequest) (bool, error if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/k8s/worker_reset.go b/pkg/cloudapi/k8s/worker_reset.go index ffa7611..ccc0902 100644 --- a/pkg/cloudapi/k8s/worker_reset.go +++ b/pkg/cloudapi/k8s/worker_reset.go @@ -7,21 +7,28 @@ import ( "strconv" ) +// Request struct for hard reset kubernetes cluster type WorkerResetRequest struct { - K8SID uint64 `url:"k8sId"` + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // ID of the workers compute group + // Required: true WorkersGroupID uint64 `url:"workersGroupId"` - WorkerID uint64 `url:"workerId"` + + // Compute ID of worker node to reset + // Required: true + WorkerID uint64 `url:"workerId"` } -func (krq WorkerResetRequest) Validate() error { +func (krq WorkerResetRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } - if krq.WorkersGroupID == 0 { return errors.New("validation-error: field WorkersGroupID can not be empty or equal to 0") } - if krq.WorkerID == 0 { return errors.New("validation-error: field WorkerID can not be empty or equal to 0") } @@ -29,8 +36,9 @@ func (krq WorkerResetRequest) Validate() error { return nil } +// WorkerReset hard reset (compute start + stop) worker node of the Kubernetes cluster func (k8s K8S) WorkerReset(ctx context.Context, req WorkerResetRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -46,5 +54,6 @@ func (k8s K8S) WorkerReset(ctx context.Context, req WorkerResetRequest) (bool, e if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/k8s/worker_restart.go b/pkg/cloudapi/k8s/worker_restart.go index afc0329..5249d42 100644 --- a/pkg/cloudapi/k8s/worker_restart.go +++ b/pkg/cloudapi/k8s/worker_restart.go @@ -7,21 +7,28 @@ import ( "strconv" ) +// Request struct for restart worker node type WorkerRestartRequest struct { - K8SID uint64 `url:"k8sId"` + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // ID of the workers compute group + // Required: true WorkersGroupID uint64 `url:"workersGroupId"` - WorkerID uint64 `url:"workerId"` + + // Compute ID of worker node to restart + // Required: true + WorkerID uint64 `url:"workerId"` } -func (krq WorkerRestartRequest) Validate() error { +func (krq WorkerRestartRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } - if krq.WorkersGroupID == 0 { return errors.New("validation-error: field WorkersGroupID can not be empty or equal to 0") } - if krq.WorkerID == 0 { return errors.New("validation-error: field WorkerID can not be empty or equal to 0") } @@ -29,8 +36,9 @@ func (krq WorkerRestartRequest) Validate() error { return nil } +// WorkerRestart soft restart (reboot OS) worker node of the Kubernetes cluster func (k8s K8S) WorkerRestart(ctx context.Context, req WorkerRestartRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -46,5 +54,6 @@ func (k8s K8S) WorkerRestart(ctx context.Context, req WorkerRestartRequest) (boo if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/k8s/workers_group_add.go b/pkg/cloudapi/k8s/workers_group_add.go index 7e79284..e0189bc 100644 --- a/pkg/cloudapi/k8s/workers_group_add.go +++ b/pkg/cloudapi/k8s/workers_group_add.go @@ -7,44 +7,61 @@ import ( "strconv" ) +// Request struct for add workers group type WorkersGroupAddRequest struct { - K8SID uint64 `url:"k8sId"` - Name string `url:"name"` - Labels []string `url:"labels"` - Taints []string `url:"taints"` - Annotations []string `url:"annotations"` - WorkerNum uint `url:"workerNum"` - WorkerCPU uint `url:"workerCpu"` - WorkerRam uint `url:"workerRam"` - WorkerDisk uint `url:"workerDisk"` + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // Worker group name + // Required: true + Name string `url:"name"` + + // List of strings with labels for worker group + // i.e: ["label1=value1", "label2=value2"] + // Required: false + Labels []string `url:"labels,omitempty"` + + // List of strings with taints for worker group + // i.e: ["key1=value1:NoSchedule", "key2=value2:NoExecute"] + // Required: false + Taints []string `url:"taints,omitempty"` + + // List of strings with annotations for worker group + // i.e: ["key1=value1", "key2=value2"] + // Required: false + Annotations []string `url:"annotations,omitempty"` + + // Number of worker nodes to create + // Required: false + WorkerNum uint64 `url:"workerNum,omitempty"` + + // Worker node CPU count + // Required: false + WorkerCPU uint64 `url:"workerCpu,omitempty"` + + // Worker node RAM volume in MB + // Required: false + WorkerRAM uint64 `url:"workerRam,omitempty"` + + // Worker node boot disk size in GB If 0 is specified, size is defined by the OS image size + // Required: false + WorkerDisk uint64 `url:"workerDisk,omitempty"` } -func (krq WorkersGroupAddRequest) Validate() error { +func (krq WorkersGroupAddRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } - if krq.Name == "" { - return errors.New("validation-error: field Name can not be empty") + return errors.New("validation-error: field Name must be set") } - - if krq.WorkerNum == 0 { - return errors.New("validation-error: field WorkerNum can not be empty or equal to 0") - } - - if krq.WorkerCPU == 0 { - return errors.New("validation-error: field WorkerCPU can not be empty or equal to 0") - } - - if krq.WorkerRam < 1024 { - return errors.New("validation-error: field WorkerRam must be greater or equal 1024") - } - return nil } +// WorkersGroupAdd adds workers group to Kubernetes cluster func (k8s K8S) WorkersGroupAdd(ctx context.Context, req WorkersGroupAddRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -60,5 +77,6 @@ func (k8s K8S) WorkersGroupAdd(ctx context.Context, req WorkersGroupAddRequest) if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/k8s/workers_group_delete.go b/pkg/cloudapi/k8s/workers_group_delete.go index d07f73c..d56e10e 100644 --- a/pkg/cloudapi/k8s/workers_group_delete.go +++ b/pkg/cloudapi/k8s/workers_group_delete.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for delete workers group type WorkersGroupDeleteRequest struct { - K8SID uint64 `url:"k8sId"` + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // Worker group ID + // Required: true WorkersGroupID uint64 `url:"workersGroupId"` } -func (krq WorkersGroupDeleteRequest) Validate() error { +func (krq WorkersGroupDeleteRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } - if krq.WorkersGroupID == 0 { return errors.New("validation-error: field WorkersGroupID can not be empty or equal to 0") } @@ -24,8 +29,9 @@ func (krq WorkersGroupDeleteRequest) Validate() error { return nil } +// WorkersGroupDelete deletes workers group from Kubernetes cluster func (k8s K8S) WorkersGroupDelete(ctx context.Context, req WorkersGroupDeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -41,5 +47,6 @@ func (k8s K8S) WorkersGroupDelete(ctx context.Context, req WorkersGroupDeleteReq if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudapi/k8s/workers_group_get_by_name.go b/pkg/cloudapi/k8s/workers_group_get_by_name.go index e187ce0..5fbf4d5 100644 --- a/pkg/cloudapi/k8s/workers_group_get_by_name.go +++ b/pkg/cloudapi/k8s/workers_group_get_by_name.go @@ -7,16 +7,21 @@ import ( "net/http" ) +// Request struct for get information about worker group type WorkersGroupGetByNameRequest struct { - K8SID uint64 `url:"k8sId"` - GroupName string `url:"groupName "` + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // Worker group name + // Required: true + GroupName string `url:"groupName"` } -func (krq WorkersGroupGetByNameRequest) Validate() error { +func (krq WorkersGroupGetByNameRequest) validate() error { if krq.K8SID == 0 { return errors.New("validation-error: field K8SID can not be empty or equal to 0") } - if krq.GroupName == "" { return errors.New("validation-error: field WorkersGroupID can not be empty") } @@ -24,8 +29,9 @@ func (krq WorkersGroupGetByNameRequest) Validate() error { return nil } -func (k8s K8S) WorkersGroupGetByName(ctx context.Context, req WorkersGroupGetByNameRequest) (*K8SGroup, error) { - err := req.Validate() +// WorkersGroupGetByName gets worker group metadata by name +func (k8s K8S) WorkersGroupGetByName(ctx context.Context, req WorkersGroupGetByNameRequest) (*RecordK8SGroups, error) { + err := req.validate() if err != nil { return nil, err } @@ -37,12 +43,12 @@ func (k8s K8S) WorkersGroupGetByName(ctx context.Context, req WorkersGroupGetByN return nil, err } - group := &K8SGroup{} + info := RecordK8SGroups{} - err = json.Unmarshal(res, group) + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return group, nil + return &info, nil } diff --git a/pkg/cloudapi/kvmppc.go b/pkg/cloudapi/kvmppc.go index 72aabfd..f189f62 100644 --- a/pkg/cloudapi/kvmppc.go +++ b/pkg/cloudapi/kvmppc.go @@ -2,6 +2,7 @@ package cloudapi import "github.com/rudecs/decort-sdk/pkg/cloudapi/kvmppc" -func (ca *CloudApi) KVMPPC() *kvmppc.KVMPPC { +// Accessing the KVMPPC method group +func (ca *CloudAPI) KVMPPC() *kvmppc.KVMPPC { return kvmppc.New(ca.client) } diff --git a/pkg/cloudapi/kvmppc/create.go b/pkg/cloudapi/kvmppc/create.go index 444412a..f06083c 100644 --- a/pkg/cloudapi/kvmppc/create.go +++ b/pkg/cloudapi/kvmppc/create.go @@ -7,26 +7,84 @@ import ( "strconv" ) +// Request struct for create KVM PowerPC VM type CreateRequest struct { - RGID uint64 `url:"rgId"` - Name string `url:"name"` - CPU uint64 `url:"cpu"` - RAM uint64 `url:"ram"` - ImageID uint64 `url:"imageId"` - BootDisk uint64 `url:"bootDisk,omitempty"` - SepID uint64 `url:"sepId,omitempty"` - Pool string `url:"pool,omitempty"` - NetType string `url:"netType,omitempty"` - NetID uint64 `url:"netId,omitempty"` - IPAddr string `url:"ipAddr,omitempty"` - Userdata string `url:"userdata,omitempty"` + // ID of the resource group, which will own this VM + // Required: true + RGID uint64 `url:"rgId"` + + // Name of this VM. + // Must be unique among all VMs (including those in DELETED state) in target resource group + // Required: true + Name string `url:"name"` + + // Number CPUs to allocate to this VM + // Required: true + CPU uint64 `url:"cpu"` + + // Volume of RAM in MB to allocate to this VM + // Required: true + RAM uint64 `url:"ram"` + + // ID of the OS image to base this VM on; + // Could be boot disk image or CD-ROM image + // Required: true + ImageID uint64 `url:"imageId"` + + // Size of the boot disk in GB + // Required: false + BootDisk uint64 `url:"bootDisk,omitempty"` + + // ID of SEP to create boot disk on. + // Uses images SEP ID if not set + // Required: false + SEPID uint64 `url:"sepId,omitempty"` + + // Pool to use if sepId is set, can be also empty if needed to be chosen by system + // Required: false + Pool string `url:"pool,omitempty"` + + // Network type + // Should be one of: + // - VINS + // - EXTNET + // - NONE + // Required: false + NetType string `url:"netType,omitempty"` + + // Network ID for connect to, + // for EXTNET - external network ID, + // for ViNS - ViNS ID, + // when netType is not "NONE" + // Required: false + NetID uint64 `url:"netId,omitempty"` + + // IP address to assign to this VM when connecting to the specified network + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // Input data for cloud-init facility + // Required: false + Userdata string `url:"userdata,omitempty"` + + // Text description of this VM + // Required: false Description string `url:"desc,omitempty"` - Start bool `url:"start,omitempty"` - IS string `url:"IS,omitempty"` - IPAType string `url:"ipaType,omitempty"` + + // Start VM upon success + // Required: false + Start bool `url:"start,omitempty"` + + // System name + // Required: false + IS string `url:"IS,omitempty"` + + // Compute purpose + // Required: false + IPAType string `url:"ipaType,omitempty"` } -func (krq CreateRequest) Validate() error { +func (krq CreateRequest) validate() error { if krq.RGID == 0 { return errors.New("validation-error: field RGID can not be empty or equal to 0") } @@ -46,16 +104,15 @@ func (krq CreateRequest) Validate() error { return nil } +// Create creates KVM PowerPC VM based on specified OS image func (k KVMPPC) Create(ctx context.Context, req CreateRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } - url := "/kvmppc/create" - prefix := "/cloudapi" + url := "/cloudapi/kvmppc/create" - url = prefix + url res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return 0, err @@ -65,6 +122,6 @@ func (k KVMPPC) Create(ctx context.Context, req CreateRequest) (uint64, error) { if err != nil { return 0, err } - return result, nil + return result, nil } diff --git a/pkg/cloudapi/kvmppc/create_blank.go b/pkg/cloudapi/kvmppc/create_blank.go index 824300b..2a1dcdd 100644 --- a/pkg/cloudapi/kvmppc/create_blank.go +++ b/pkg/cloudapi/kvmppc/create_blank.go @@ -7,21 +7,63 @@ import ( "strconv" ) +// Request struct for create KVM PowerPC VM from scratch type CreateBlankRequest struct { - RGID uint64 `url:"rgId"` - Name string `url:"name"` - CPU uint64 `url:"cpu"` - RAM uint64 `url:"ram"` - BootDisk uint64 `url:"bootDisk"` - SepID uint64 `url:"sepId"` - Pool string `url:"pool"` - NetType string `url:"netType,omitempty"` - NetID uint64 `url:"netId,omitempty"` - IPAddr string `url:"ipAddr,omitempty"` + // ID of the resource group, which will own this VM + // Required: true + RGID uint64 `url:"rgId"` + + // Name of this VM. + // Must be unique among all VMs (including those in DELETED state) in target resource group + // Required: true + Name string `url:"name"` + + // Number CPUs to allocate to this VM + // Required: true + CPU uint64 `url:"cpu"` + + // Volume of RAM in MB to allocate to this VM + // Required: true + RAM uint64 `url:"ram"` + + // Size of the boot disk in GB + // Required: true + BootDisk uint64 `url:"bootDisk"` + + // ID of SEP to create boot disk on. + // Uses images SEP ID if not set + // Required: true + SEPID uint64 `url:"sepId"` + + // Pool to use if SEP ID is set, can be also empty if needed to be chosen by system + // Required: true + Pool string `url:"pool"` + + // Network type + // Should be one of: + // - VINS + // - EXTNET + // - NONE + // Required: false + NetType string `url:"netType,omitempty"` + + // Network ID for connect to, + // for EXTNET - external network ID, + // for VINS - VINS ID, + // when network type is not "NONE" + // Required: false + NetID uint64 `url:"netId,omitempty"` + + // IP address to assign to this VM when connecting to the specified network + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // Text description of this VM + // Required: false Description string `url:"desc,omitempty"` } -func (krq CreateBlankRequest) Validate() error { +func (krq CreateBlankRequest) validate() error { if krq.RGID == 0 { return errors.New("validation-error: field RGID can not be empty or equal to 0") } @@ -37,7 +79,7 @@ func (krq CreateBlankRequest) Validate() error { if krq.BootDisk == 0 { return errors.New("validation-error: field BootDisk can not be empty or equal to 0") } - if krq.SepID == 0 { + if krq.SEPID == 0 { return errors.New("validation-error: field SepID can not be empty or equal to 0") } if krq.Pool == "" { @@ -47,16 +89,15 @@ func (krq CreateBlankRequest) Validate() error { return nil } +// CreateBlank creates KVM PowerPC VM from scratch func (k KVMPPC) CreateBlank(ctx context.Context, req CreateBlankRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } - url := "/kvmppc/createBlank" - prefix := "/cloudapi" + url := "/cloudapi/kvmppc/createBlank" - url = prefix + url res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return 0, err @@ -66,6 +107,6 @@ func (k KVMPPC) CreateBlank(ctx context.Context, req CreateBlankRequest) (uint64 if err != nil { return 0, err } - return result, nil + return result, nil } diff --git a/pkg/cloudapi/kvmppc/kvmppc.go b/pkg/cloudapi/kvmppc/kvmppc.go index 050b6d5..bb7bfa5 100644 --- a/pkg/cloudapi/kvmppc/kvmppc.go +++ b/pkg/cloudapi/kvmppc/kvmppc.go @@ -1,13 +1,16 @@ +// API to manage KVM PowerPC compute instances (PPC VMs) package kvmppc import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to KVMPPC type KVMPPC struct { client interfaces.Caller } +// Builder for KVMPPC endpoints func New(client interfaces.Caller) *KVMPPC { return &KVMPPC{ client, diff --git a/pkg/cloudapi/kvmx86.go b/pkg/cloudapi/kvmx86.go index 8c2bd72..1b50d61 100644 --- a/pkg/cloudapi/kvmx86.go +++ b/pkg/cloudapi/kvmx86.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudapi/kvmx86" ) -func (ca *CloudApi) KVMX86() *kvmx86.KVMX86 { +// Accessing the KVMX86 method group +func (ca *CloudAPI) KVMX86() *kvmx86.KVMX86 { return kvmx86.New(ca.client) } diff --git a/pkg/cloudapi/kvmx86/create.go b/pkg/cloudapi/kvmx86/create.go index cb728d1..af4a362 100644 --- a/pkg/cloudapi/kvmx86/create.go +++ b/pkg/cloudapi/kvmx86/create.go @@ -7,26 +7,84 @@ import ( "strconv" ) +// Request struct for create KVM x86 VM type CreateRequest struct { - RGID uint64 `url:"rgId"` - Name string `url:"name"` - CPU uint64 `url:"cpu"` - RAM uint64 `url:"ram"` - ImageID uint64 `url:"imageId"` - BootDisk uint64 `url:"bootDisk,omitempty"` - SepID uint64 `url:"sepId,omitempty"` - Pool string `url:"pool,omitempty"` - NetType string `url:"netType,omitempty"` - NetID uint64 `url:"netId,omitempty"` - IPAddr string `url:"ipAddr,omitempty"` - Userdata string `url:"userdata,omitempty"` + // ID of the resource group, which will own this VM + // Required: true + RGID uint64 `url:"rgId"` + + // Name of this VM. + // Must be unique among all VMs (including those in DELETED state) in target resource group + // Required: true + Name string `url:"name"` + + // Number CPUs to allocate to this VM + // Required: true + CPU uint64 `url:"cpu"` + + // Volume of RAM in MB to allocate to this VM + // Required: true + RAM uint64 `url:"ram"` + + // ID of the OS image to base this VM on; + // Could be boot disk image or CD-ROM image + // Required: true + ImageID uint64 `url:"imageId"` + + // Size of the boot disk in GB + // Required: false + BootDisk uint64 `url:"bootDisk,omitempty"` + + // ID of SEP to create boot disk on. + // Uses images SEP ID if not set + // Required: false + SepID uint64 `url:"sepId,omitempty"` + + // Pool to use if sepId is set, can be also empty if needed to be chosen by system + // Required: false + Pool string `url:"pool,omitempty"` + + // Network type + // Should be one of: + // - VINS + // - EXTNET + // - NONE + // Required: false + NetType string `url:"netType,omitempty"` + + // Network ID for connect to, + // for EXTNET - external network ID, + // for VINS - VINS ID, + // when network type is not "NONE" + // Required: false + NetID uint64 `url:"netId,omitempty"` + + // IP address to assign to this VM when connecting to the specified network + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // Input data for cloud-init facility + // Required: false + Userdata string `url:"userdata,omitempty"` + + // Text description of this VM + // Required: false Description string `url:"desc,omitempty"` - Start bool `url:"start,omitempty"` - IS string `url:"IS,omitempty"` - IPAType string `url:"ipaType,omitempty"` + + // Start VM upon success + // Required: false + Start bool `url:"start,omitempty"` + + // System name + // Required: false + IS string `url:"IS,omitempty"` + + // Compute purpose + // Required: false + IPAType string `url:"ipaType,omitempty"` } -func (krq CreateRequest) Validate() error { +func (krq CreateRequest) validate() error { if krq.RGID == 0 { return errors.New("validation-error: field RGID can not be empty or equal to 0") } @@ -46,16 +104,15 @@ func (krq CreateRequest) Validate() error { return nil } +// Create creates KVM x86 VM based on specified OS image func (k KVMX86) Create(ctx context.Context, req CreateRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } - url := "/kvmx86/create" - prefix := "/cloudapi" + url := "/cloudapi/kvmx86/create" - url = prefix + url res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return 0, err @@ -65,6 +122,6 @@ func (k KVMX86) Create(ctx context.Context, req CreateRequest) (uint64, error) { if err != nil { return 0, err } - return result, nil + return result, nil } diff --git a/pkg/cloudapi/kvmx86/create_blank.go b/pkg/cloudapi/kvmx86/create_blank.go index c9e114e..0ee097d 100644 --- a/pkg/cloudapi/kvmx86/create_blank.go +++ b/pkg/cloudapi/kvmx86/create_blank.go @@ -7,21 +7,63 @@ import ( "strconv" ) +// Request struct for create KVM x86 VM from scratch type CreateBlankRequest struct { - RGID uint64 `url:"rgId"` - Name string `url:"name"` - CPU uint64 `url:"cpu"` - RAM uint64 `url:"ram"` - BootDisk uint64 `url:"bootDisk"` - SepID uint64 `url:"sepId"` - Pool string `url:"pool"` - NetType string `url:"netType,omitempty"` - NetID uint64 `url:"netId,omitempty"` - IPAddr string `url:"ipAddr,omitempty"` + // ID of the resource group, which will own this VM + // Required: true + RGID uint64 `url:"rgId"` + + // Name of this VM. + // Must be unique among all VMs (including those in DELETED state) in target resource group + // Required: true + Name string `url:"name"` + + // Number CPUs to allocate to this VM + // Required: true + CPU uint64 `url:"cpu"` + + // Volume of RAM in MB to allocate to this VM + // Required: true + RAM uint64 `url:"ram"` + + // Size of the boot disk in GB + // Required: true + BootDisk uint64 `url:"bootDisk"` + + // ID of SEP to create boot disk on. + // Uses images SEP ID if not set + // Required: true + SEPID uint64 `url:"sepId"` + + // Pool to use if sepId is set, can be also empty if needed to be chosen by system + // Required: true + Pool string `url:"pool"` + + // Network type + // Should be one of: + // - VINS + // - EXTNET + // - NONE + // Required: false + NetType string `url:"netType,omitempty"` + + // Network ID for connect to, + // for EXTNET - external network ID, + // for VINS - VINS ID, + // when network type is not "NONE" + // Required: false + NetID uint64 `url:"netId,omitempty"` + + // IP address to assign to this VM when connecting to the specified network + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // Text description of this VM + // Required: false Description string `url:"desc,omitempty"` } -func (krq CreateBlankRequest) Validate() error { +func (krq CreateBlankRequest) validate() error { if krq.RGID == 0 { return errors.New("validation-error: field RGID can not be empty or equal to 0") } @@ -37,7 +79,7 @@ func (krq CreateBlankRequest) Validate() error { if krq.BootDisk == 0 { return errors.New("validation-error: field BootDisk can not be empty or equal to 0") } - if krq.SepID == 0 { + if krq.SEPID == 0 { return errors.New("validation-error: field SepID can not be empty or equal to 0") } if krq.Pool == "" { @@ -47,16 +89,15 @@ func (krq CreateBlankRequest) Validate() error { return nil } +// CreateBlank creates KVM x86 VM from scratch func (k KVMX86) CreateBlank(ctx context.Context, req CreateBlankRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } - url := "/kvmx86/createBlank" - prefix := "/cloudapi" + url := "/cloudapi/kvmx86/createBlank" - url = prefix + url res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return 0, err @@ -66,6 +107,6 @@ func (k KVMX86) CreateBlank(ctx context.Context, req CreateBlankRequest) (uint64 if err != nil { return 0, err } - return result, nil + return result, nil } diff --git a/pkg/cloudapi/kvmx86/kvmx86.go b/pkg/cloudapi/kvmx86/kvmx86.go index 62ff0b1..8b410a3 100644 --- a/pkg/cloudapi/kvmx86/kvmx86.go +++ b/pkg/cloudapi/kvmx86/kvmx86.go @@ -1,13 +1,16 @@ +// API to manage KVM x86 compute instances (x86 VMs) package kvmx86 import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to KVMX86 type KVMX86 struct { client interfaces.Caller } +// Builder for KVMX86 endpoints func New(client interfaces.Caller) *KVMX86 { return &KVMX86{ client, diff --git a/pkg/cloudapi/lb.go b/pkg/cloudapi/lb.go index 6a4362c..c5e2c2a 100644 --- a/pkg/cloudapi/lb.go +++ b/pkg/cloudapi/lb.go @@ -2,6 +2,7 @@ package cloudapi import "github.com/rudecs/decort-sdk/pkg/cloudapi/lb" -func (ca *CloudApi) LB() *lb.LB { +// Accessing the LB method group +func (ca *CloudAPI) LB() *lb.LB { return lb.New(ca.client) } diff --git a/pkg/cloudapi/lb/backend_create.go b/pkg/cloudapi/lb/backend_create.go index 1d909a9..491134b 100644 --- a/pkg/cloudapi/lb/backend_create.go +++ b/pkg/cloudapi/lb/backend_create.go @@ -7,25 +7,69 @@ import ( "strconv" ) +// Request struct for create backend type BackendCreateRequest struct { - LBID uint64 `url:"lbId"` + // ID of the load balancer instance to backendCreate + // Required: true + LBID uint64 `url:"lbId"` + + // Must be unique among all backends of this load balancer - name of the new backend to create + // Required: true BackendName string `url:"backendName"` - Algorithm string `url:"algorithm,omitempty"` - Inter uint64 `url:"inter,omitempty"` - DownInter uint64 `url:"downinter,omitempty"` - Rise uint `url:"rise,omitempty"` - Fall uint `url:"fall,omitempty"` - SlowStart uint64 `url:"slowstart,omitempty"` - MaxConn uint `url:"maxconn,omitempty"` - MaxQueue uint `url:"maxqueue,omitempty"` - Weight uint `url:"weight,omitempty"` + + // Algorithm + // Should be one of: + // - roundrobin + // - static-rr + // - leastconn + // Required: false + Algorithm string `url:"algorithm,omitempty"` + + // Interval in milliseconds between two consecutive availability + // checks of the server that is considered available + // Required: false + Inter uint64 `url:"inter,omitempty"` + + // Interval in milliseconds between two consecutive checks to + // restore the availability of a server that is currently considered unavailable + // Required: false + DownInter uint64 `url:"downinter,omitempty"` + + // Number of checks that the server must pass in order to get the available status + // and be included in the balancing scheme again + // Required: false + Rise uint64 `url:"rise,omitempty"` + + // Number of consecutive failed availability checks, + // after which the previously considered available server receives the status of + // unavailable and is temporarily excluded from the balancing scheme + // Required: false + Fall uint64 `url:"fall,omitempty"` + + // Interval in milliseconds from the moment the server receives the available status, + // after which the number of actually allowed connections to this server will be returned to 100% of the set limit + // Required: false + SlowStart uint64 `url:"slowstart,omitempty"` + + // Limit of simultaneous connections to the server. When this limit is reached, + // the server is temporarily excluded from the balancing scheme + // Required: false + MaxConn uint64 `url:"maxconn,omitempty"` + + // Limit of connections waiting in the queue. + // When this limit is reached, all subsequent connections will be forwarded to other servers + // Required: false + MaxQueue uint64 `url:"maxqueue,omitempty"` + + // Server weight for use in weight balancing algorithms + // Required: false + Weight uint64 `url:"weight,omitempty"` } -func (lbrq BackendCreateRequest) Validate() error { +func (lbrq BackendCreateRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } - if lbrq.BackendName == "" { return errors.New("validation-error: field BackendName can not be empty") } @@ -33,8 +77,9 @@ func (lbrq BackendCreateRequest) Validate() error { return nil } +// BackendCreate creates new backend on the specified load balancer func (l LB) BackendCreate(ctx context.Context, req BackendCreateRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/lb/backend_delete.go b/pkg/cloudapi/lb/backend_delete.go index 158464e..c3dd483 100644 --- a/pkg/cloudapi/lb/backend_delete.go +++ b/pkg/cloudapi/lb/backend_delete.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for delete backend type BackendDeleteRequest struct { - LBID uint64 `url:"lbId"` + // ID of the load balancer instance to BackendDelete + // Required: true + LBID uint64 `url:"lbId"` + + // Cannot be emtpy string - name of the backend to delete + // Required: true BackendName string `url:"backendName"` } -func (lbrq BackendDeleteRequest) Validate() error { +func (lbrq BackendDeleteRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } - if lbrq.BackendName == "" { return errors.New("validation-error: field BackendName can not be empty") } @@ -24,8 +29,10 @@ func (lbrq BackendDeleteRequest) Validate() error { return nil } +// BackendDelete deletes backend from the specified load balancer. +// Warning: you cannot undo this action! func (l LB) BackendDelete(ctx context.Context, req BackendDeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/lb/backend_server_add.go b/pkg/cloudapi/lb/backend_server_add.go index 7c84509..7e7df41 100644 --- a/pkg/cloudapi/lb/backend_server_add.go +++ b/pkg/cloudapi/lb/backend_server_add.go @@ -7,40 +7,83 @@ import ( "strconv" ) +// Request struct for add server definition to the backend type BackendServerAddRequest struct { - LBID uint64 `url:"lbId"` + // ID of the load balancer instance to BackendServerAdd + // Required: true + LBID uint64 `url:"lbId"` + + // Must match one of the existing backens - name of the backend to add servers to + // Required: true BackendName string `url:"backendName"` - ServerName string `url:"serverName"` - Address string `url:"address"` - Port uint `url:"port"` - Check string `url:"check,omitempty"` - Inter uint64 `url:"inter,omitempty"` - DownInter uint64 `url:"downinter,omitempty"` - Rise uint `url:"rise,omitempty"` - Fall uint `url:"fall,omitempty"` - SlowStart uint64 `url:"slowstart,omitempty"` - MaxConn uint `url:"maxconn,omitempty"` - MaxQueue uint `url:"maxqueue,omitempty"` - Weight uint `url:"weight,omitempty"` + + // Must be unique among all servers defined for this backend - name of the server definition to add + // Required: true + ServerName string `url:"serverName"` + + // IP address of the server + // Required: true + Address string `url:"address"` + + // Port number on the server + // Required: true + Port uint64 `url:"port"` + + // Set to disabled if this server should be used regardless of its state + // Required: false + Check string `url:"check,omitempty"` + + // Interval in milliseconds between two consecutive availability checks of the server that is considered available + // Required: false + Inter uint64 `url:"inter,omitempty"` + + // Interval in milliseconds between two consecutive checks to restore + // the availability of a server that is currently considered unavailable + // Required: false + DownInter uint64 `url:"downinter,omitempty"` + + // Number of checks that the server must pass in order to get + // the available status and be included in the balancing scheme again + // Required: false + Rise uint64 `url:"rise,omitempty"` + + // Number of consecutive failed availability checks, + // after which the previously considered available server receives the status of unavailable and + // is temporarily excluded from the balancing scheme + // Required: false + Fall uint64 `url:"fall,omitempty"` + + // Interval in milliseconds from the moment the server receives the available status, + // after which the number of actually allowed connections to this server will be returned to 100% of the set limit + // Required: false + SlowStart uint64 `url:"slowstart,omitempty"` + + // Limit of simultaneous connections to the server. When this limit is reached, the server is temporarily excluded from the balancing scheme + // Required: false + MaxConn uint64 `url:"maxconn,omitempty"` + + // Limit of connections waiting in the queue. When this limit is reached, all subsequent connections will be forwarded to other servers + // Required: false + MaxQueue uint64 `url:"maxqueue,omitempty"` + + // Server weight for use in weight balancing algorithms + // Required: false + Weight uint64 `url:"weight,omitempty"` } -func (lbrq BackendServerAddRequest) Validate() error { +func (lbrq BackendServerAddRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } - if lbrq.BackendName == "" { return errors.New("validation-error: field BackendName can not be empty") } - if lbrq.ServerName == "" { return errors.New("validation-error: field ServerName can not be empty") } - if lbrq.Address == "" { return errors.New("validation-error: field Address can not be empty") } - if lbrq.Port == 0 { return errors.New("validation-error: field Port can not be empty or equal to 0") } @@ -48,8 +91,9 @@ func (lbrq BackendServerAddRequest) Validate() error { return nil } +// BackendServerAdd adds server definition to the backend on the specified load balancer func (l LB) BackendServerAdd(ctx context.Context, req BackendServerAddRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/lb/backend_server_delete.go b/pkg/cloudapi/lb/backend_server_delete.go index d572167..6edd9d0 100644 --- a/pkg/cloudapi/lb/backend_server_delete.go +++ b/pkg/cloudapi/lb/backend_server_delete.go @@ -7,21 +7,28 @@ import ( "strconv" ) +// Request struct for delete server definition type BackendServerDeleteRequest struct { - LBID uint64 `url:"lbId"` + // ID of the load balancer instance to BackendServerDelete + // Required: true + LBID uint64 `url:"lbId"` + + // Must match one of the existing backens - name of the backend to add servers to + // Required: true BackendName string `url:"backendName"` - ServerName string `url:"serverName"` + + // Must be unique among all servers defined for this backend - name of the server definition to add + // Required: true + ServerName string `url:"serverName"` } -func (lbrq BackendServerDeleteRequest) Validate() error { +func (lbrq BackendServerDeleteRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } - if lbrq.BackendName == "" { return errors.New("validation-error: field BackendName can not be empty") } - if lbrq.ServerName == "" { return errors.New("validation-error: field ServerName can not be empty") } @@ -29,8 +36,10 @@ func (lbrq BackendServerDeleteRequest) Validate() error { return nil } +// BackendServerDelete deletes server definition from the backend on the specified load balancer. +// Warning: you cannot undo this action! func (l LB) BackendServerDelete(ctx context.Context, req BackendServerDeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/lb/backend_server_update.go b/pkg/cloudapi/lb/backend_server_update.go index c191f84..d003d2d 100644 --- a/pkg/cloudapi/lb/backend_server_update.go +++ b/pkg/cloudapi/lb/backend_server_update.go @@ -7,40 +7,83 @@ import ( "strconv" ) +// Request struct for update server type BackendServerUpdateRequest struct { - LBID uint64 `url:"lbId"` + // ID of the load balancer instance to BackendServerAdd + // Required: true + LBID uint64 `url:"lbId"` + + // Must match one of the existing backens - name of the backend to add servers to + // Required: true BackendName string `url:"backendName"` - ServerName string `url:"serverName"` - Address string `url:"address"` - Port uint `url:"port"` - Check string `url:"check,omitempty"` - Inter uint64 `url:"inter,omitempty"` - DownInter uint64 `url:"downinter,omitempty"` - Rise uint `url:"rise,omitempty"` - Fall uint `url:"fall,omitempty"` - SlowStart uint64 `url:"slowstart,omitempty"` - MaxConn uint `url:"maxconn,omitempty"` - MaxQueue uint `url:"maxqueue,omitempty"` - Weight uint `url:"weight,omitempty"` + + // Must be unique among all servers defined for this backend - name of the server definition to add + // Required: true + ServerName string `url:"serverName"` + + // IP address of the server + // Required: true + Address string `url:"address"` + + // Port number on the server + // Required: true + Port uint64 `url:"port"` + + // Set to disabled if this server should be used regardless of its state + // Required: false + Check string `url:"check,omitempty"` + + // Interval in milliseconds between two consecutive availability checks of the server that is considered available + // Required: false + Inter uint64 `url:"inter,omitempty"` + + // Interval in milliseconds between two consecutive checks to restore + // the availability of a server that is currently considered unavailable + // Required: false + DownInter uint64 `url:"downinter,omitempty"` + + // Number of checks that the server must pass in order to get + // the available status and be included in the balancing scheme again + // Required: false + Rise uint64 `url:"rise,omitempty"` + + // Number of consecutive failed availability checks, + // after which the previously considered available server receives the status of unavailable and + // is temporarily excluded from the balancing scheme + // Required: false + Fall uint64 `url:"fall,omitempty"` + + // Interval in milliseconds from the moment the server receives the available status, + // after which the number of actually allowed connections to this server will be returned to 100% of the set limit + // Required: false + SlowStart uint64 `url:"slowstart,omitempty"` + + // Limit of simultaneous connections to the server. When this limit is reached, the server is temporarily excluded from the balancing scheme + // Required: false + MaxConn uint64 `url:"maxconn,omitempty"` + + // Limit of connections waiting in the queue. When this limit is reached, all subsequent connections will be forwarded to other servers + // Required: false + MaxQueue uint64 `url:"maxqueue,omitempty"` + + // Server weight for use in weight balancing algorithms + // Required: false + Weight uint64 `url:"weight,omitempty"` } -func (lbrq BackendServerUpdateRequest) Validate() error { +func (lbrq BackendServerUpdateRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } - if lbrq.BackendName == "" { return errors.New("validation-error: field BackendName can not be empty") } - if lbrq.ServerName == "" { return errors.New("validation-error: field ServerName can not be empty") } - if lbrq.Address == "" { return errors.New("validation-error: field Address can not be empty") } - if lbrq.Port == 0 { return errors.New("validation-error: field Port can not be empty or equal to 0") } @@ -48,8 +91,9 @@ func (lbrq BackendServerUpdateRequest) Validate() error { return nil } +// BackendServerUpdate updates server definition on the backend of load balancer func (l LB) BackendServerUpdate(ctx context.Context, req BackendServerUpdateRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/lb/backend_update.go b/pkg/cloudapi/lb/backend_update.go index 85b7efb..0af4073 100644 --- a/pkg/cloudapi/lb/backend_update.go +++ b/pkg/cloudapi/lb/backend_update.go @@ -7,25 +7,69 @@ import ( "strconv" ) +// Request struct for update backend type BackendUpdateRequest struct { - LBID uint64 `url:"lbId"` + // ID of the load balancer instance to backendCreate + // Required: true + LBID uint64 `url:"lbId"` + + // Must be unique among all backends of this load balancer - name of the new backend to create + // Required: true BackendName string `url:"backendName"` - Algorithm string `url:"algorithm,omitempty"` - Inter uint64 `url:"inter,omitempty"` - DownInter uint64 `url:"downinter,omitempty"` - Rise uint `url:"rise,omitempty"` - Fall uint `url:"fall,omitempty"` - SlowStart uint64 `url:"slowstart,omitempty"` - MaxConn uint `url:"maxconn,omitempty"` - MaxQueue uint `url:"maxqueue,omitempty"` - Weight uint `url:"weight,omitempty"` + + // Algorithm + // Should be one of: + // - roundrobin + // - static-rr + // - leastconn + // Required: false + Algorithm string `url:"algorithm,omitempty"` + + // Interval in milliseconds between two consecutive availability + // checks of the server that is considered available + // Required: false + Inter uint64 `url:"inter,omitempty"` + + // Interval in milliseconds between two consecutive checks to + // restore the availability of a server that is currently considered unavailable + // Required: false + DownInter uint64 `url:"downinter,omitempty"` + + // Number of checks that the server must pass in order to get the available status + // and be included in the balancing scheme again + // Required: false + Rise uint64 `url:"rise,omitempty"` + + // Number of consecutive failed availability checks, + // after which the previously considered available server receives the status of + // unavailable and is temporarily excluded from the balancing scheme + // Required: false + Fall uint64 `url:"fall,omitempty"` + + // Interval in milliseconds from the moment the server receives the available status, + // after which the number of actually allowed connections to this server will be returned to 100% of the set limit + // Required: false + SlowStart uint64 `url:"slowstart,omitempty"` + + // Limit of simultaneous connections to the server. When this limit is reached, + // the server is temporarily excluded from the balancing scheme + // Required: false + MaxConn uint64 `url:"maxconn,omitempty"` + + // Limit of connections waiting in the queue. + // When this limit is reached, all subsequent connections will be forwarded to other servers + // Required: false + MaxQueue uint64 `url:"maxqueue,omitempty"` + + // Server weight for use in weight balancing algorithms + // Required: false + Weight uint64 `url:"weight,omitempty"` } -func (lbrq BackendUpdateRequest) Validate() error { +func (lbrq BackendUpdateRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } - if lbrq.BackendName == "" { return errors.New("validation-error: field BackendName can not be empty") } @@ -33,8 +77,9 @@ func (lbrq BackendUpdateRequest) Validate() error { return nil } +// BackendUpdate updates existing backend on the specified load balancer. Note that backend name cannot be changed func (l LB) BackendUpdate(ctx context.Context, req BackendUpdateRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/lb/config_reset.go b/pkg/cloudapi/lb/config_reset.go index 7e76056..b1a024f 100644 --- a/pkg/cloudapi/lb/config_reset.go +++ b/pkg/cloudapi/lb/config_reset.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for reset config type ConfigResetRequest struct { + // ID of the load balancer instance to ConfigReset + // Required: true LBID uint64 `url:"lbId"` } -func (lbrq ConfigResetRequest) Validate() error { +func (lbrq ConfigResetRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } @@ -19,8 +22,10 @@ func (lbrq ConfigResetRequest) Validate() error { return nil } +// ConfigReset reset current software configuration of the specified load balancer. +// Warning: this action cannot be undone! func (l LB) ConfigReset(ctx context.Context, req ConfigResetRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/lb/create.go b/pkg/cloudapi/lb/create.go index 4de6548..a760c54 100644 --- a/pkg/cloudapi/lb/create.go +++ b/pkg/cloudapi/lb/create.go @@ -7,28 +7,44 @@ import ( "strings" ) +// Request struct for create load balancer type CreateRequest struct { - RGID uint64 `url:"rgId"` - Name string `url:"name"` - ExtNetID uint64 `url:"extnetId"` - VINSID uint64 `url:"vinsId"` - Start bool `url:"start"` + // ID of the resource group where this load balancer instance will be located + // Required: true + RGID uint64 `url:"rgId"` + + // Name of the load balancer. + // Must be unique among all load balancers in this Resource Group + // Required: true + Name string `url:"name"` + + // External network to connect this load balancer to + // Required: true + ExtNetID uint64 `url:"extnetId"` + + // Internal network (VINS) to connect this load balancer to + // Required: true + VINSID uint64 `url:"vinsId"` + + // Start now Load balancer + // Required: false + Start bool `url:"start"` + + // Text description of this load balancer + // Required: false Description string `url:"desc,omitempty"` } -func (lbrq CreateRequest) Validate() error { +func (lbrq CreateRequest) validate() error { if lbrq.RGID == 0 { return errors.New("validation-error: field RGID can not be empty or equal to 0") } - if lbrq.Name == "" { return errors.New("validation-error: field Name can not be empty") } - if lbrq.ExtNetID == 0 { return errors.New("validation-error: field ExtNetID can not be empty or equal to 0") } - if lbrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } @@ -36,8 +52,9 @@ func (lbrq CreateRequest) Validate() error { return nil } +// Create method will create a new load balancer instance func (l LB) Create(ctx context.Context, req CreateRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } @@ -49,5 +66,7 @@ func (l LB) Create(ctx context.Context, req CreateRequest) (string, error) { return "", err } - return strings.ReplaceAll(string(res), "\"", ""), nil + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil } diff --git a/pkg/cloudapi/lb/delete.go b/pkg/cloudapi/lb/delete.go index 5c85d0b..ea8bb94 100644 --- a/pkg/cloudapi/lb/delete.go +++ b/pkg/cloudapi/lb/delete.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for delete load balancer type DeleteRequest struct { - LBID uint64 `url:"lbId"` - Permanently bool `url:"permanently"` + // ID of the load balancer instance to delete + // Required: true + LBID uint64 `url:"lbId"` + + // Set to true to delete load balancer immediately bypassing recycle bin + // Required: false + Permanently bool `url:"permanently,omitempty"` } -func (lbrq DeleteRequest) Validate() error { +func (lbrq DeleteRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } @@ -20,8 +26,9 @@ func (lbrq DeleteRequest) Validate() error { return nil } +// Delete deletes specified load balancer func (l LB) Delete(ctx context.Context, req DeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/lb/disable_enable.go b/pkg/cloudapi/lb/disable_enable.go index c293459..e2dca40 100644 --- a/pkg/cloudapi/lb/disable_enable.go +++ b/pkg/cloudapi/lb/disable_enable.go @@ -7,11 +7,14 @@ import ( "strconv" ) -type DisabelEnableRequest struct { +// Request struct for disable/enable load balancer +type DisableEnableRequest struct { + // ID of the load balancer instance to disable/enable + // Required: true LBID uint64 `url:"lbId"` } -func (lbrq DisabelEnableRequest) Validate() error { +func (lbrq DisableEnableRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (lbrq DisabelEnableRequest) Validate() error { return nil } -func (l LB) Disable(ctx context.Context, req DisabelEnableRequest) (bool, error) { - err := req.Validate() +// Disable disables specified load balancer instance +func (l LB) Disable(ctx context.Context, req DisableEnableRequest) (bool, error) { + err := req.validate() if err != nil { return false, err } @@ -40,8 +44,9 @@ func (l LB) Disable(ctx context.Context, req DisabelEnableRequest) (bool, error) return result, nil } -func (l LB) Enable(ctx context.Context, req DisabelEnableRequest) (bool, error) { - err := req.Validate() +// Enable enables specified load balancer instance +func (l LB) Enable(ctx context.Context, req DisableEnableRequest) (bool, error) { + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/lb/frontend_bind.go b/pkg/cloudapi/lb/frontend_bind.go index bcab4a7..b960df4 100644 --- a/pkg/cloudapi/lb/frontend_bind.go +++ b/pkg/cloudapi/lb/frontend_bind.go @@ -7,23 +7,39 @@ import ( "strings" ) +// Request struct for frontend bind type FrontendBindRequest struct { - LBID uint64 `url:"lbId"` - FrontendName string `url:"frontendName"` - BindingName string `url:"bindingName"` + // ID of the load balancer instance to FrontendBind + // Required: true + LBID uint64 `url:"lbId"` + + // Name of the frontend to update + // Required: true + FrontendName string `url:"frontendName"` + + // Name of the binding to update + // Required: true + BindingName string `url:"bindingName"` + + // If specified must be within the IP range of either Ext Net or ViNS, + // where this load balancer is connected - new IP address to use for this binding. + // If omitted, current IP address is retained + // Required: false BindingAddress string `url:"bindingAddress,omitempty"` - BindingPort uint `url:"bindingPort,omitempty"` + + // New port number to use for this binding. + // If omitted, current port number is retained + // Required: false + BindingPort uint64 `url:"bindingPort,omitempty"` } -func (lbrq FrontendBindRequest) Validate() error { +func (lbrq FrontendBindRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } - if lbrq.FrontendName == "" { return errors.New("validation-error: field FrontendName can not be empty") } - if lbrq.BindingName == "" { return errors.New("validation-error: field BindingName can not be empty") } @@ -31,8 +47,9 @@ func (lbrq FrontendBindRequest) Validate() error { return nil } +// FrontendBind bind frontend from specified load balancer instance func (l LB) FrontendBind(ctx context.Context, req FrontendBindRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } @@ -44,5 +61,7 @@ func (l LB) FrontendBind(ctx context.Context, req FrontendBindRequest) (string, return "", err } - return strings.ReplaceAll(string(res), "\"", ""), nil + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil } diff --git a/pkg/cloudapi/lb/frontend_bind_delete.go b/pkg/cloudapi/lb/frontend_bind_delete.go index ec392c5..cddf789 100644 --- a/pkg/cloudapi/lb/frontend_bind_delete.go +++ b/pkg/cloudapi/lb/frontend_bind_delete.go @@ -7,21 +7,28 @@ import ( "strings" ) +// Request struct for delete bind type FrontendBindDeleteRequest struct { - LBID uint64 `url:"lbId"` + // ID of the load balancer instance to FrontendBindDelete + // Required: true + LBID uint64 `url:"lbId"` + + // Name of the frontend to delete + // Required: true FrontendName string `url:"frontendName"` - BindingName string `url:"bindingName"` + + // Name of the binding to delete + // Required: true + BindingName string `url:"bindingName"` } -func (lbrq FrontendBindDeleteRequest) Validate() error { +func (lbrq FrontendBindDeleteRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } - if lbrq.FrontendName == "" { return errors.New("validation-error: field FrontendName can not be empty") } - if lbrq.BindingName == "" { return errors.New("validation-error: field BindingName can not be empty") } @@ -29,8 +36,9 @@ func (lbrq FrontendBindDeleteRequest) Validate() error { return nil } +// FrontendBindDelete deletes binding from the specified load balancer frontend func (l LB) FrontendBindDelete(ctx context.Context, req FrontendBindDeleteRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } @@ -42,5 +50,7 @@ func (l LB) FrontendBindDelete(ctx context.Context, req FrontendBindDeleteReques return "", err } - return strings.ReplaceAll(string(res), "\"", ""), nil + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil } diff --git a/pkg/cloudapi/lb/frontend_bind_update.go b/pkg/cloudapi/lb/frontend_bind_update.go index 8afce1e..2ece2c3 100644 --- a/pkg/cloudapi/lb/frontend_bind_update.go +++ b/pkg/cloudapi/lb/frontend_bind_update.go @@ -7,23 +7,39 @@ import ( "strings" ) +// Request struct for update binding type FrontendBindUpdateRequest struct { - LBID uint64 `url:"lbId"` - FrontendName string `url:"frontendName"` - BindingName string `url:"bindingName"` + // ID of the load balancer instance to FrontendBindUpdate + // Required: true + LBID uint64 `url:"lbId"` + + // Name of the frontend to update + // Required: true + FrontendName string `url:"frontendName"` + + // Name of the binding to update + // Required: true + BindingName string `url:"bindingName"` + + // If specified must be within the IP range of either Ext Net or ViNS, + // where this load balancer is connected - new IP address to use for this binding. + // If omitted, current IP address is retained + // Required: false BindingAddress string `url:"bindingAddress,omitempty"` - BindingPort uint `url:"bindingPort,omitempty"` + + // New port number to use for this binding. + // If omitted, current port number is retained + // Required: false + BindingPort uint64 `url:"bindingPort,omitempty"` } -func (lbrq FrontendBindUpdateRequest) Validate() error { +func (lbrq FrontendBindUpdateRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } - if lbrq.FrontendName == "" { return errors.New("validation-error: field FrontendName can not be empty") } - if lbrq.BindingName == "" { return errors.New("validation-error: field BindingName can not be empty") } @@ -31,8 +47,9 @@ func (lbrq FrontendBindUpdateRequest) Validate() error { return nil } +// FrontendBindUpdate updates binding for the specified load balancer frontend func (l LB) FrontendBindUpdate(ctx context.Context, req FrontendBindUpdateRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } @@ -44,5 +61,7 @@ func (l LB) FrontendBindUpdate(ctx context.Context, req FrontendBindUpdateReques return "", err } - return strings.ReplaceAll(string(res), "\"", ""), nil + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil } diff --git a/pkg/cloudapi/lb/frontend_create.go b/pkg/cloudapi/lb/frontend_create.go index 86d97e1..c1d92a0 100644 --- a/pkg/cloudapi/lb/frontend_create.go +++ b/pkg/cloudapi/lb/frontend_create.go @@ -7,21 +7,30 @@ import ( "strconv" ) +// Request struct for create frontend type FrontendCreateRequest struct { - LBID uint64 `url:"lbId"` + // ID of the load balancer instance to FrontendCreate + // Required: true + LBID uint64 `url:"lbId"` + + // Must be unique among all frontends of + // this load balancer - name of the new frontend to create + // Required: true FrontendName string `url:"frontendName"` - BackendName string `url:"backendName"` + + // Should be one of the backends existing on + // this load balancer - name of the backend to use + // Required: true + BackendName string `url:"backendName"` } -func (lbrq FrontendCreateRequest) Validate() error { +func (lbrq FrontendCreateRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } - if lbrq.FrontendName == "" { return errors.New("validation-error: field FrontendName can not be empty") } - if lbrq.BackendName == "" { return errors.New("validation-error: field BackendName can not be empty") } @@ -29,8 +38,9 @@ func (lbrq FrontendCreateRequest) Validate() error { return nil } +// FrontendCreate creates new frontend on the specified load balancer func (l LB) FrontendCreate(ctx context.Context, req FrontendCreateRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/lb/frontend_delete.go b/pkg/cloudapi/lb/frontend_delete.go index c82501e..2e3ce5c 100644 --- a/pkg/cloudapi/lb/frontend_delete.go +++ b/pkg/cloudapi/lb/frontend_delete.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for delete frontend type FrontendDeleteRequest struct { - LBID uint64 `url:"lbId"` + // ID of the load balancer instance to FrontendDelete + // Required: true + LBID uint64 `url:"lbId"` + + // Name of the frontend to delete + // Required: true FrontendName string `url:"frontendName"` } -func (lbrq FrontendDeleteRequest) Validate() error { +func (lbrq FrontendDeleteRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } - if lbrq.FrontendName == "" { return errors.New("validation-error: field FrontendName can not be empty") } @@ -24,8 +29,10 @@ func (lbrq FrontendDeleteRequest) Validate() error { return nil } +// FrontendDelete deletes frontend from the specified load balancer. +// Warning: you cannot undo this action! func (l LB) FrontendDelete(ctx context.Context, req FrontendDeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/lb/get.go b/pkg/cloudapi/lb/get.go index 5eb9bd3..ca09c20 100644 --- a/pkg/cloudapi/lb/get.go +++ b/pkg/cloudapi/lb/get.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get detailed information about load balancer type GetRequest struct { + // ID of the load balancer to get details for + // Required: true LBID uint64 `url:"lbId"` } -func (lbrq GetRequest) Validate() error { +func (lbrq GetRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } @@ -19,25 +22,26 @@ func (lbrq GetRequest) Validate() error { return nil } -func (l LB) Get(ctx context.Context, req GetRequest) (*LoadBalancer, error) { - err := req.Validate() +// Get gets detailed information about load balancer +func (l LB) Get(ctx context.Context, req GetRequest) (*RecordLB, error) { + err := req.validate() if err != nil { return nil, err } url := "/cloudapi/lb/get" - lbRaw, err := l.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := l.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - lb := &LoadBalancer{} - err = json.Unmarshal(lbRaw, lb) + info := RecordLB{} + + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return lb, nil - + return &info, nil } diff --git a/pkg/cloudapi/lb/lb.go b/pkg/cloudapi/lb/lb.go index c8f444b..1718493 100644 --- a/pkg/cloudapi/lb/lb.go +++ b/pkg/cloudapi/lb/lb.go @@ -1,13 +1,16 @@ +// API to manage load balancer instance package lb import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to load balancer type LB struct { client interfaces.Caller } +// Builder for load balancer func New(client interfaces.Caller) *LB { return &LB{ client, diff --git a/pkg/cloudapi/lb/list.go b/pkg/cloudapi/lb/list.go index bc0bd23..9292ac0 100644 --- a/pkg/cloudapi/lb/list.go +++ b/pkg/cloudapi/lb/list.go @@ -6,26 +6,36 @@ import ( "net/http" ) +// Request struct for get list of load balancers type ListRequest struct { - IncludeDeleted bool `url:"includedeleted"` - Page uint64 `url:"page"` - Size uint64 `url:"size"` + // Included deleted load balancers + // Required: false + IncludeDeleted bool `url:"includedeleted,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (l LB) List(ctx context.Context, req ListRequest) (LBList, error) { +// List gets list all load balancers +func (l LB) List(ctx context.Context, req ListRequest) (ListLB, error) { url := "/cloudapi/lb/list" - lbListRaw, err := l.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := l.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - lbList := LBList{} - err = json.Unmarshal(lbListRaw, &lbList) + list := ListLB{} + + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return lbList, nil - + return list, nil } diff --git a/pkg/cloudapi/lb/list_deleted.go b/pkg/cloudapi/lb/list_deleted.go index 88b2871..737d88c 100644 --- a/pkg/cloudapi/lb/list_deleted.go +++ b/pkg/cloudapi/lb/list_deleted.go @@ -6,25 +6,32 @@ import ( "net/http" ) +// Request struct for get list of deleted load balancers type ListDeletedRequest struct { - Page uint64 `url:"page"` - Size uint64 `url:"size"` + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: true + Size uint64 `url:"size,omitempty"` } -func (l LB) ListDeleted(ctx context.Context, req ListDeletedRequest) (LBList, error) { +// ListDeleted gets list of deleted load balancers +func (l LB) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListLB, error) { url := "/cloudapi/lb/listDeleted" - lbListRaw, err := l.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := l.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - lbList := LBList{} - err = json.Unmarshal(lbListRaw, &lbList) + list := ListLB{} + + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return lbList, nil - + return list, nil } diff --git a/pkg/cloudapi/lb/models.go b/pkg/cloudapi/lb/models.go index 805d253..44eb31e 100644 --- a/pkg/cloudapi/lb/models.go +++ b/pkg/cloudapi/lb/models.go @@ -1,89 +1,226 @@ package lb -type LoadBalancer struct { - HAMode bool `json:"HAmode"` - ACL interface{} `json:"acl"` - Backends []Backend `json:"backends"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - Description string `json:"desc"` - DPAPIUser string `json:"dpApiUser"` - ExtNetID uint64 `json:"extnetId"` - Frontends []Frontend `json:"frontends"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - ImageID uint64 `json:"imageId"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - PrimaryNode Node `json:"primaryNode"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - SecondaryNode Node `json:"secondaryNode"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - VINSID uint64 `json:"vinsId"` +// Detailed information about load balancer +type RecordLB struct { + //HAMode + HAMode bool `json:"HAmode"` + + // Access Control List + ACL interface{} `json:"acl"` + + // List of load balancer backends + Backends ListBackends `json:"backends"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // DPAPIUser + DPAPIUser string `json:"dpApiUser"` + + // External network ID + ExtNetID uint64 `json:"extnetId"` + + // List of load balancer frontends + Frontends ListFrontends `json:"frontends"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Image ID + ImageID uint64 `json:"imageId"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Primary node + PrimaryNode RecordNode `json:"primaryNode"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Secondary node + SecondaryNode RecordNode `json:"secondaryNode"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // VINS ID + VINSID uint64 `json:"vinsId"` } -type LoadBalancerDetailed struct { +// Main information about load balancer +type ItemLoadBalancer struct { + // DPAPIPassword DPAPIPassword string `json:"dpApiPassword"` - LoadBalancer + // Detailed information about load balancer + RecordLB } -type Backend struct { - Algorithm string `json:"algorithm"` - GUID string `json:"guid"` - Name string `json:"name"` - ServerDefaultSettings ServerSettings `json:"serverDefaultSettings"` - Servers []Server `json:"servers"` +// List of load balancers +type ListLB []ItemLoadBalancer + +// Main information about backend +type ItemBackend struct { + // Algorithm + Algorithm string `json:"algorithm"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` + + // Server settings + ServerDefaultSettings RecordServerSettings `json:"serverDefaultSettings"` + + // List of servers + Servers ListServers `json:"servers"` } -type LBList []LoadBalancerDetailed +// List of backends +type ListBackends []ItemBackend -type ServerSettings struct { - Inter uint64 `json:"inter"` - GUID string `json:"guid"` +// Server settings +type RecordServerSettings struct { + // Inter + Inter uint64 `json:"inter"` + + // GUID + GUID string `json:"guid"` + + // DownInter DownInter uint64 `json:"downinter"` - Rise uint64 `json:"rise"` - Fall uint64 `json:"fall"` + + // Rise + Rise uint64 `json:"rise"` + + // Fall + Fall uint64 `json:"fall"` + + // SlowStart SlowStart uint64 `json:"slowstart"` - MaxConn uint64 `json:"maxconn"` - MaxQueue uint64 `json:"maxqueue"` - Weight uint64 `json:"weight"` + + // Max connections + MaxConn uint64 `json:"maxconn"` + + // Max queue + MaxQueue uint64 `json:"maxqueue"` + + // Weight + Weight uint64 `json:"weight"` } -type Server struct { - Address string `json:"address"` - Check string `json:"check"` - GUID string `json:"guid"` - Name string `json:"name"` - Port uint64 `json:"port"` - ServerSettings ServerSettings `json:"serverSettings"` +// Main information about server +type ItemServer struct { + + // Address + Address string `json:"address"` + + // Check + Check string `json:"check"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` + + // Port + Port uint64 `json:"port"` + + // Server settings + ServerSettings RecordServerSettings `json:"serverSettings"` } -type Node struct { - BackendIP string `json:"backendIp"` - ComputeID uint64 `json:"computeId"` +// List of servers +type ListServers []ItemServer + +// Main information about node +type RecordNode struct { + // Backend IP + BackendIP string `json:"backendIp"` + + // Compute ID + ComputeID uint64 `json:"computeId"` + + // Frontend IP FrontendIP string `json:"frontendIp"` - GUID string `json:"guid"` - MGMTIP string `json:"mgmtIp"` - NetworkID uint64 `json:"networkId"` + + // GUID + GUID string `json:"guid"` + + // MGMTIP + MGMTIP string `json:"mgmtIp"` + + // Network ID + NetworkID uint64 `json:"networkId"` } -type Frontend struct { - Backend string `json:"backend"` - Bindings []Binding `json:"bindings"` - GUID string `json:"guid"` - Name string `json:"name"` +// Main information about frontend +type ItemFrontend struct { + // Backend + Backend string `json:"backend"` + + // List of bindings + Bindings ListBindings `json:"bindings"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` } -type Binding struct { +// List of frontends +type ListFrontends []ItemFrontend + +// Main information about bindings +type ItemBinding struct { + // Address Address string `json:"address"` - GUID string `json:"guid"` - Name string `json:"name"` - Port uint64 `json:"port"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` + + // Port + Port uint64 `json:"port"` } + +// List of bindings +type ListBindings []ItemBinding diff --git a/pkg/cloudapi/lb/restart.go b/pkg/cloudapi/lb/restart.go index ad9d81d..172b9bf 100644 --- a/pkg/cloudapi/lb/restart.go +++ b/pkg/cloudapi/lb/restart.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for restart load balancer type RestartRequest struct { + // ID of the load balancer instance to restart + // Required: true LBID uint64 `url:"lbId"` } -func (lbrq RestartRequest) Validate() error { +func (lbrq RestartRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (lbrq RestartRequest) Validate() error { return nil } +// Restart restarts specified load balancer instance func (l LB) Restart(ctx context.Context, req RestartRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/lb/restore.go b/pkg/cloudapi/lb/restore.go index 36cd2f2..92511f8 100644 --- a/pkg/cloudapi/lb/restore.go +++ b/pkg/cloudapi/lb/restore.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for restore load balancer type RestoreRequest struct { + // ID of the load balancer instance to restore + // Required: true LBID uint64 `url:"lbId"` } -func (lbrq RestoreRequest) Validate() error { +func (lbrq RestoreRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (lbrq RestoreRequest) Validate() error { return nil } +// Restore restore load balancer from recycle bin func (l LB) Restore(ctx context.Context, req RestoreRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/lb/update.go b/pkg/cloudapi/lb/update.go index 7a8deca..e21a8b5 100644 --- a/pkg/cloudapi/lb/update.go +++ b/pkg/cloudapi/lb/update.go @@ -7,12 +7,19 @@ import ( "strconv" ) +// Request struct for update load balancer type UpdateRequest struct { - LBID uint64 `url:"lbId"` + // ID of the load balancer to update + // Required: true + LBID uint64 `url:"lbId"` + + // New description of this load balancer. + // If omitted, current description is retained + // Required: true Description string `url:"desc"` } -func (lbrq UpdateRequest) Validate() error { +func (lbrq UpdateRequest) validate() error { if lbrq.LBID == 0 { return errors.New("validation-error: field LBID can not be empty or equal to 0") } @@ -23,8 +30,9 @@ func (lbrq UpdateRequest) Validate() error { return nil } +// Update updates some of load balancer attributes func (l LB) Update(ctx context.Context, req UpdateRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/locations/get_url.go b/pkg/cloudapi/locations/get_url.go index 306319f..5ecc982 100644 --- a/pkg/cloudapi/locations/get_url.go +++ b/pkg/cloudapi/locations/get_url.go @@ -5,11 +5,10 @@ import ( "net/http" ) -func (l Locations) GetUrl(ctx context.Context) (string, error) { - url := "/locations/getUrl" - prefix := "/cloudapi" +// GetURL gets the portal URL +func (l Locations) GetURL(ctx context.Context) (string, error) { + url := "/cloudapi/locations/getUrl" - url = prefix + url res, err := l.client.DecortApiCall(ctx, http.MethodPost, url, nil) if err != nil { return "", err diff --git a/pkg/cloudapi/locations/list.go b/pkg/cloudapi/locations/list.go index 15ed0ad..e79bc94 100644 --- a/pkg/cloudapi/locations/list.go +++ b/pkg/cloudapi/locations/list.go @@ -6,27 +6,32 @@ import ( "net/http" ) +// Request struct for get list of locations type ListRequest struct { - Page uint64 `url:"page"` - Size uint64 `url:"size"` + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (l Locations) List(ctx context.Context, req ListRequest) (LocationsList, error) { - url := "/locations/list" - prefix := "/cloudapi" +// List gets list all locations +func (l Locations) List(ctx context.Context, req ListRequest) (ListLocations, error) { + url := "/cloudapi/locations/list" - url = prefix + url - locationsListRaw, err := l.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := l.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - locationsList := LocationsList{} - err = json.Unmarshal(locationsListRaw, &locationsList) + list := ListLocations{} + + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return locationsList, nil - + return list, nil } diff --git a/pkg/cloudapi/locations/locations.go b/pkg/cloudapi/locations/locations.go index 89590fd..165c5e7 100644 --- a/pkg/cloudapi/locations/locations.go +++ b/pkg/cloudapi/locations/locations.go @@ -1,13 +1,16 @@ +// API Actor api for managing locations package locations import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to locations type Locations struct { client interfaces.Caller } +// Builder for locations endpoints func New(client interfaces.Caller) *Locations { return &Locations{ client, diff --git a/pkg/cloudapi/locations/models.go b/pkg/cloudapi/locations/models.go index 80e0c52..80df20a 100644 --- a/pkg/cloudapi/locations/models.go +++ b/pkg/cloudapi/locations/models.go @@ -1,14 +1,31 @@ package locations -type Location struct { - GID uint64 `json:"gid"` - ID uint64 `json:"id"` - GUID uint64 `json:"guid"` - LocationCode string `json:"locationCode"` - Name string `json:"name"` - Flag string `json:"flag"` - Meta []interface{} `json:"_meta"` - CKey string `json:"_ckey"` +// Main information about locations +type ItemLocation struct { + // Grid ID + GID uint64 `json:"gid"` + + // ID + ID uint64 `json:"id"` + + // GUID + GUID uint64 `json:"guid"` + + // Location code + LocationCode string `json:"locationCode"` + + // Name + Name string `json:"name"` + + // Flag + Flag string `json:"flag"` + + // Meta + Meta []interface{} `json:"_meta"` + + // CKey + CKey string `json:"_ckey"` } -type LocationsList []Location +// List of locations +type ListLocations []ItemLocation diff --git a/pkg/cloudapi/locatons.go b/pkg/cloudapi/locatons.go index 6e70c20..4c4f6be 100644 --- a/pkg/cloudapi/locatons.go +++ b/pkg/cloudapi/locatons.go @@ -2,6 +2,7 @@ package cloudapi import "github.com/rudecs/decort-sdk/pkg/cloudapi/locations" -func (ca *CloudApi) Locations() *locations.Locations { +// Accessing the Locations method group +func (ca *CloudAPI) Locations() *locations.Locations { return locations.New(ca.client) } diff --git a/pkg/cloudapi/rg.go b/pkg/cloudapi/rg.go index 3175f82..c34c59e 100644 --- a/pkg/cloudapi/rg.go +++ b/pkg/cloudapi/rg.go @@ -2,6 +2,7 @@ package cloudapi import "github.com/rudecs/decort-sdk/pkg/cloudapi/rg" -func (ca *CloudApi) RG() *rg.RG { +// Accessing the RG method group +func (ca *CloudAPI) RG() *rg.RG { return rg.New(ca.client) } diff --git a/pkg/cloudapi/rg/access_grant.go b/pkg/cloudapi/rg/access_grant.go index 7bde936..ff676f1 100644 --- a/pkg/cloudapi/rg/access_grant.go +++ b/pkg/cloudapi/rg/access_grant.go @@ -9,39 +9,61 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for grant access to resource group type AccessGrantRequest struct { - RGID uint64 `url:"rgId"` - User string `url:"user"` - Right string `url:"right"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // User or group name to grant access + // Required: true + User string `url:"user"` + + // Access rights to set, one of: + // - "R" + // - "RCX" + // - "ARCXDU" + // Required: true + Right string `url:"right"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq AccessGrantRequest) Validate() error { +func (rgrq AccessGrantRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } - if rgrq.User == "" { return errors.New("field User can not be empty") } - - if !validators.StringInSlice(rgrq.Right, []string{"R", "RCX", "ARCXDU"}) { + validate := validators.StringInSlice(rgrq.Right, []string{"R", "RCX", "ARCXDU"}) + if !validate { return errors.New("field Right can only be one of 'R', 'RCX' or 'ARCXDU'") } return nil } +// AccessGrant grants user or group access to the resource group as specified func (r RG) AccessGrant(ctx context.Context, req AccessGrantRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/rg/accessGrant" + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/rg/access_revoke.go b/pkg/cloudapi/rg/access_revoke.go index 1c12409..5ab9abd 100644 --- a/pkg/cloudapi/rg/access_revoke.go +++ b/pkg/cloudapi/rg/access_revoke.go @@ -7,17 +7,25 @@ import ( "strconv" ) +// Request struct for revoke access type AccessRevokeRequest struct { - RGID uint64 `url:"rgId"` - User string `url:"user"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // User or group name to revoke access + // Required: true + User string `url:"user"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq AccessRevokeRequest) Validate() error { +func (rgrq AccessRevokeRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } - if rgrq.User == "" { return errors.New("field User can not be empty") } @@ -25,16 +33,24 @@ func (rgrq AccessRevokeRequest) Validate() error { return nil } +// AccessRevoke revokes specified user or group access from the resource group func (r RG) AccessRevoke(ctx context.Context, req AccessRevokeRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/rg/accessRevoke" + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/rg/affinity_group_computes.go b/pkg/cloudapi/rg/affinity_group_computes.go index d32307c..656c220 100644 --- a/pkg/cloudapi/rg/affinity_group_computes.go +++ b/pkg/cloudapi/rg/affinity_group_computes.go @@ -7,16 +7,21 @@ import ( "net/http" ) +// Request struct for get list of all computes with their relationships type AffinityGroupComputesRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Affinity group label + // Required: true AffinityGroup string `url:"affinityGroup"` } -func (rgrq AffinityGroupComputesRequest) Validate() error { +func (rgrq AffinityGroupComputesRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } - if rgrq.AffinityGroup == "" { return errors.New("field AffinityGroup cat not be empty") } @@ -24,21 +29,26 @@ func (rgrq AffinityGroupComputesRequest) Validate() error { return nil } -func (r RG) AffinityGroupComputes(ctx context.Context, req AffinityGroupComputesRequest) (AffinityGroupComputeList, error) { - if err := req.Validate(); err != nil { +// AffinityGroupComputes gets list of all computes with their relationships to another computes +func (r RG) AffinityGroupComputes(ctx context.Context, req AffinityGroupComputesRequest) (ListAffinityGroups, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/rg/affinityGroupComputes" - agcListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - agcList := AffinityGroupComputeList{} - if err := json.Unmarshal(agcListRaw, &agcList); err != nil { + list := ListAffinityGroups{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return agcList, nil + return list, nil } diff --git a/pkg/cloudapi/rg/affinity_groups_get.go b/pkg/cloudapi/rg/affinity_groups_get.go index 0990c87..f8d46c8 100644 --- a/pkg/cloudapi/rg/affinity_groups_get.go +++ b/pkg/cloudapi/rg/affinity_groups_get.go @@ -7,16 +7,21 @@ import ( "net/http" ) +// Request struct for get list computes from affinity group type AffinityGroupsGetRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Label affinity group + // Required: true AffinityGroup string `url:"affinityGroup"` } -func (rgrq AffinityGroupsGetRequest) Validate() error { +func (rgrq AffinityGroupsGetRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } - if rgrq.AffinityGroup == "" { return errors.New("field AffinityGroup cat not be empty") } @@ -24,21 +29,26 @@ func (rgrq AffinityGroupsGetRequest) Validate() error { return nil } +// AffinityGroupsGet gets list computes in the specified affinity group func (r RG) AffinityGroupsGet(ctx context.Context, req AffinityGroupsGetRequest) ([]uint64, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/rg/affinityGroupsGet" - agListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - agList := []uint64{} - if err := json.Unmarshal(agListRaw, &agList); err != nil { + list := []uint64{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return agList, nil + return list, nil } diff --git a/pkg/cloudapi/rg/affinity_groups_list.go b/pkg/cloudapi/rg/affinity_groups_list.go index 8672fd2..7213074 100644 --- a/pkg/cloudapi/rg/affinity_groups_list.go +++ b/pkg/cloudapi/rg/affinity_groups_list.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list of affinity groups from resource group type AffinityGroupsListRequest struct { + // Resource group ID + // Required: true RGID uint64 `url:"rgId"` } -func (rgrq AffinityGroupsListRequest) Validate() error { +func (rgrq AffinityGroupsListRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } @@ -19,21 +22,26 @@ func (rgrq AffinityGroupsListRequest) Validate() error { return nil } +// AffinityGroupsList gets all currently defined affinity groups in this resource group with compute IDs func (r RG) AffinityGroupsList(ctx context.Context, req AffinityGroupsListRequest) (map[string][]uint64, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/rg/affinityGroupsList" - agListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - agList := map[string][]uint64{} - if err := json.Unmarshal(agListRaw, &agList); err != nil { + list := map[string][]uint64{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return agList, nil + return list, nil } diff --git a/pkg/cloudapi/rg/audits.go b/pkg/cloudapi/rg/audits.go index 7adf7cd..a5aee7e 100644 --- a/pkg/cloudapi/rg/audits.go +++ b/pkg/cloudapi/rg/audits.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get audit type AuditsRequest struct { + // Resource group ID + // Required: true RGID uint64 `url:"rgId"` } -func (rgrq AuditsRequest) Validate() error { +func (rgrq AuditsRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } @@ -19,21 +22,26 @@ func (rgrq AuditsRequest) Validate() error { return nil } -func (r RG) Audits(ctx context.Context, req AuditsRequest) (AuditList, error) { - if err := req.Validate(); err != nil { +// Audits gets audit records for the specified resource group object +func (r RG) Audits(ctx context.Context, req AuditsRequest) (ListAudits, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/rg/audits" - auditListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - auditList := AuditList{} - if err := json.Unmarshal(auditListRaw, &auditList); err != nil { + list := ListAudits{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return auditList, nil + return list, nil } diff --git a/pkg/cloudapi/rg/create.go b/pkg/cloudapi/rg/create.go index c163ffc..f2ae3ba 100644 --- a/pkg/cloudapi/rg/create.go +++ b/pkg/cloudapi/rg/create.go @@ -5,53 +5,134 @@ import ( "errors" "net/http" "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for create resource group type CreateRequest struct { - AccountID uint64 `url:"accountId"` - GID uint64 `url:"gid"` - Name string `url:"name"` - MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` - MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` - MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + // Account, which will own this resource group + // Required: true + AccountID uint64 `url:"accountId"` + + // Grid ID + // Required: true + GID uint64 `url:"gid"` + + // Name of this resource group. Must be unique within the account + // Required: true + Name string `url:"name"` + + // Max size of memory in MB + // Required: false + MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` + + // Max size of aggregated virtual disks in GB + // Required: false + MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` + + // Max number of CPU cores + // Required: false + MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + + // Max sent/received network transfer peering + // Required: false MaxNetworkPeerTransfer uint64 `url:"maxNetworkPeerTransfer,omitempty"` - MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"` - Owner string `url:"owner,omitempty"` - DefNet string `url:"def_net,omitempty"` - IPCIDR string `url:"ipcidr,omitempty"` - Desc string `url:"desc,omitempty"` - Reason string `url:"reason,omitempty"` - ExtNetID uint64 `url:"extNetId,omitempty"` - ExtIP string `url:"extIp,omitempty"` - RegisterComputes bool `url:"registerComputes,omitempty"` + + // Max number of assigned public IPs + // Required: false + MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"` + + // Username - owner of this resource group. + // Leave blank to set current user as owner + // Required: false + Owner string `url:"owner,omitempty"` + + // Type of the default network for this resource group. + // virtual machines created in this resource group will be by default connected to this network. + // Allowed values are: + // - PRIVATE + // - PUBLIC + // - NONE + // Required: false + DefNet string `url:"def_net,omitempty"` + + // Private network IP CIDR if default network PRIVATE + // Required: false + IPCIDR string `url:"ipcidr,omitempty"` + + // Text description of this resource group + // Required: false + Description string `url:"desc,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` + + // External network ID + // Required: false + ExtNetID uint64 `url:"extNetId,omitempty"` + + // External IP address + // Required: false + ExtIP string `url:"extIp,omitempty"` + + // Register computes in registration system + // Required: false + RegisterComputes bool `url:"registerComputes,omitempty"` + + // Resource types available to create in this account + // Each element in a resource type slice must be one of: + // - compute + // - vins + // - k8s + // - openshift + // - lb + // - flipgroup + // Required: false + ResTypes []string `url:"resourceTypes,omitempty"` } -func (rgrq CreateRequest) Validate() error { +func (rgrq CreateRequest) validate() error { if rgrq.AccountID == 0 { return errors.New("field AccountID can not be empty or equal to 0") } - if rgrq.GID == 0 { return errors.New("field GID can not be empty or equal to 0") } - if len(rgrq.Name) < 2 { return errors.New("field Name can not be shorter than two bytes") } + if len(rgrq.ResTypes) > 0 { + for _, value := range rgrq.ResTypes { + validate := validators.StringInSlice(value, []string{"compute", "vins", "k8s", "openshift", "lb", "flipgroup"}) + if !validate { + return errors.New("validation-error: Every resource type specified should be one of [compute, vins, k8s, openshift, lb, flipgroup]") + } + } + } return nil } +// Create creates resource group func (r RG) Create(ctx context.Context, req CreateRequest) (uint64, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return 0, err } url := "/cloudapi/rg/create" + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return 0, err } - return strconv.ParseUint(string(res), 10, 64) + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil } diff --git a/pkg/cloudapi/rg/delete.go b/pkg/cloudapi/rg/delete.go index b1201a8..eb76e1f 100644 --- a/pkg/cloudapi/rg/delete.go +++ b/pkg/cloudapi/rg/delete.go @@ -7,14 +7,27 @@ import ( "strconv" ) +// Request struct for delete resource group type DeleteRequest struct { - RGID uint64 `url:"rgId"` - Force bool `url:"force,omitempty"` - Permanently bool `url:"permanently,omitempty"` - Reason string `url:"reason,omitempty"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Set to True if you want force delete non-empty resource group + // Required: false + Force bool `url:"force,omitempty"` + + // Set to True if you want to destroy resource group and all linked resources, if any, immediately. + // Otherwise, they will be placed into recycle bin and could be restored later within recycle bin's purge period + // Required: false + Permanently bool `url:"permanently,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` } -func (rgrq DeleteRequest) Validate() error { +func (rgrq DeleteRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } @@ -22,16 +35,24 @@ func (rgrq DeleteRequest) Validate() error { return nil } +// Delete deletes resource group func (r RG) Delete(ctx context.Context, req DeleteRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/rg/delete" + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/rg/disable.go b/pkg/cloudapi/rg/disable.go index 14c5b69..a5e7a9c 100644 --- a/pkg/cloudapi/rg/disable.go +++ b/pkg/cloudapi/rg/disable.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for disable resource group type DisableRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq DisableRequest) Validate() error { +func (rgrq DisableRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } @@ -20,16 +26,24 @@ func (rgrq DisableRequest) Validate() error { return nil } +// Disable disables resource group func (r RG) Disable(ctx context.Context, req DisableRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/rg/disable" + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/rg/enable.go b/pkg/cloudapi/rg/enable.go index 1176a33..4e96c34 100644 --- a/pkg/cloudapi/rg/enable.go +++ b/pkg/cloudapi/rg/enable.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for enable resource group type EnableRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq EnableRequest) Validate() error { +func (rgrq EnableRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } @@ -20,16 +26,24 @@ func (rgrq EnableRequest) Validate() error { return nil } +// Enable enables resource group func (r RG) Enable(ctx context.Context, req EnableRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/rg/enable" + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/rg/get.go b/pkg/cloudapi/rg/get.go index f4ff89e..362bf03 100644 --- a/pkg/cloudapi/rg/get.go +++ b/pkg/cloudapi/rg/get.go @@ -7,12 +7,18 @@ import ( "net/http" ) +// Request struct for get detailed information about resource group type GetRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq GetRequest) Validate() error { +func (rgrq GetRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } @@ -20,21 +26,26 @@ func (rgrq GetRequest) Validate() error { return nil } -func (r RG) Get(ctx context.Context, req GetRequest) (*ResourceGroup, error) { - if err := req.Validate(); err != nil { +// Get gets current configuration of the resource group +func (r RG) Get(ctx context.Context, req GetRequest) (*RecordResourceGroup, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/rg/get" - rgRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - rg := &ResourceGroup{} - if err := json.Unmarshal(rgRaw, rg); err != nil { + info := RecordResourceGroup{} + + err = json.Unmarshal(res, &info) + if err != nil { return nil, err } - return rg, nil + return &info, nil } diff --git a/pkg/cloudapi/rg/list.go b/pkg/cloudapi/rg/list.go index 79b76e9..0040b87 100644 --- a/pkg/cloudapi/rg/list.go +++ b/pkg/cloudapi/rg/list.go @@ -6,23 +6,36 @@ import ( "net/http" ) +// Request struct for get list of resource groups type ListRequest struct { - IncludeDeleted bool `url:"includedeleted,omitempty"` - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` + // Included deleted resource groups + // Required: false + IncludeDeleted bool `url:"includedeleted,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (r RG) List(ctx context.Context, req ListRequest) (ResourceGroupList, error) { +// List gets list of all resource groups the user has access to +func (r RG) List(ctx context.Context, req ListRequest) (ListResourceGroups, error) { url := "/cloudapi/rg/list" - rgListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - rgList := ResourceGroupList{} - if err := json.Unmarshal(rgListRaw, &rgList); err != nil { + list := ListResourceGroups{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return rgList, nil + return list, nil } diff --git a/pkg/cloudapi/rg/list_computes.go b/pkg/cloudapi/rg/list_computes.go index 87ee79b..0d88191 100644 --- a/pkg/cloudapi/rg/list_computes.go +++ b/pkg/cloudapi/rg/list_computes.go @@ -7,12 +7,18 @@ import ( "net/http" ) +// Request struct for get list of computes type ListComputesRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq ListComputesRequest) Validate() error { +func (rgrq ListComputesRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } @@ -20,21 +26,26 @@ func (rgrq ListComputesRequest) Validate() error { return nil } -func (r RG) ListComputes(ctx context.Context, req ListComputesRequest) (ComputeList, error) { - if err := req.Validate(); err != nil { +// ListComputes gets list of all compute instances under specified resource group, accessible by the user +func (r RG) ListComputes(ctx context.Context, req ListComputesRequest) (ListComputes, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/rg/listComputes" - computeListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - computeList := ComputeList{} - if err := json.Unmarshal(computeListRaw, &computeList); err != nil { + list := ListComputes{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return computeList, nil + return list, nil } diff --git a/pkg/cloudapi/rg/list_deleted.go b/pkg/cloudapi/rg/list_deleted.go index 3c50f1d..568b735 100644 --- a/pkg/cloudapi/rg/list_deleted.go +++ b/pkg/cloudapi/rg/list_deleted.go @@ -6,22 +6,32 @@ import ( "net/http" ) +// Request struct for get list deleted resource groups type ListDeletedRequest struct { + // Page number + // Required: false Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false Size uint64 `url:"size,omitempty"` } -func (r RG) ListDeleted(ctx context.Context, req ListDeletedRequest) (ResourceGroupList, error) { +// ListDeleted gets list all deleted resource groups the user has access to +func (r RG) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListResourceGroups, error) { url := "/cloudapi/rg/listDeleted" - rgListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - rgList := ResourceGroupList{} - if err := json.Unmarshal(rgListRaw, &rgList); err != nil { + list := ListResourceGroups{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return rgList, nil + return list, nil } diff --git a/pkg/cloudapi/rg/list_lb.go b/pkg/cloudapi/rg/list_lb.go index e7de5f3..a5ce14c 100644 --- a/pkg/cloudapi/rg/list_lb.go +++ b/pkg/cloudapi/rg/list_lb.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list load balancers type ListLBRequest struct { + // Resource group ID + // Required: true RGID uint64 `url:"rgId"` } -func (rgrq ListLBRequest) Validate() error { +func (rgrq ListLBRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } @@ -19,21 +22,26 @@ func (rgrq ListLBRequest) Validate() error { return nil } -func (r RG) ListLB(ctx context.Context, req ListLBRequest) (LBList, error) { - if err := req.Validate(); err != nil { +// ListLB gets list all load balancers in the specified resource group, accessible by the user +func (r RG) ListLB(ctx context.Context, req ListLBRequest) (ListLB, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/rg/listLb" - lbListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - lbList := LBList{} - if err := json.Unmarshal(lbListRaw, &lbList); err != nil { + list := ListLB{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return lbList, nil + return list, nil } diff --git a/pkg/cloudapi/rg/list_pfw.go b/pkg/cloudapi/rg/list_pfw.go index 0b6b4b0..651e595 100644 --- a/pkg/cloudapi/rg/list_pfw.go +++ b/pkg/cloudapi/rg/list_pfw.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list port forward rules type ListPFWRequest struct { + // Resource group ID + // Required: true RGID uint64 `url:"rgId"` } -func (rgrq ListPFWRequest) Validate() error { +func (rgrq ListPFWRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } @@ -19,21 +22,26 @@ func (rgrq ListPFWRequest) Validate() error { return nil } -func (r RG) ListPFW(ctx context.Context, req ListPFWRequest) (PortForwardList, error) { - if err := req.Validate(); err != nil { +// ListPFW gets list port forward rules for the specified resource group +func (r RG) ListPFW(ctx context.Context, req ListPFWRequest) (ListPortForwards, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/rg/listPFW" - pfwListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - pfwList := PortForwardList{} - if err := json.Unmarshal(pfwListRaw, &pfwList); err != nil { + list := ListPortForwards{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return pfwList, nil + return list, nil } diff --git a/pkg/cloudapi/rg/list_vins.go b/pkg/cloudapi/rg/list_vins.go index e8cca3b..18135d7 100644 --- a/pkg/cloudapi/rg/list_vins.go +++ b/pkg/cloudapi/rg/list_vins.go @@ -7,12 +7,18 @@ import ( "net/http" ) +// Request struct for get list VINSes type ListVINSRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq ListVINSRequest) Validate() error { +func (rgrq ListVINSRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } @@ -20,21 +26,26 @@ func (rgrq ListVINSRequest) Validate() error { return nil } -func (r RG) ListVINS(ctx context.Context, req ListVINSRequest) (VINSList, error) { - if err := req.Validate(); err != nil { +// ListVINS gets list all ViNSes under specified resource group, accessible by the user +func (r RG) ListVINS(ctx context.Context, req ListVINSRequest) (ListVINS, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/rg/listVins" - VINSListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - VINSList := VINSList{} - if err := json.Unmarshal(VINSListRaw, &VINSList); err != nil { + list := ListVINS{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return VINSList, nil + return list, nil } diff --git a/pkg/cloudapi/rg/models.go b/pkg/cloudapi/rg/models.go index 662b52f..d275b46 100644 --- a/pkg/cloudapi/rg/models.go +++ b/pkg/cloudapi/rg/models.go @@ -1,234 +1,592 @@ package rg -type ResourceGroup struct { - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - ACL []ACL `json:"acl"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DefNetID int64 `json:"def_net_id"` - DefNetType string `json:"def_net_type"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - Desc string `json:"desc"` - Dirty bool `json:"dirty"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - LockStatus string `json:"lockStatus"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - RegisterComputes bool `json:"registerComputes"` - ResourceLimits ResourceLimits `json:"resourceLimits"` - Secret string `json:"secret"` - Status string `json:"status"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - VINS []uint64 `json:"vins"` - Computes []uint64 `json:"vms"` -} - -type ResourceGroupList []ResourceGroup - -type ACL struct { - Explicit bool `json:"explicit"` - GUID string `json:"guid"` - Right string `json:"right"` - Status string `json:"status"` - Type string `json:"type"` +// Detailed information about resource group +type RecordResourceGroup struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Access Control List + ACL ListACL `json:"acl"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // DefNetID + DefNetID int64 `json:"def_net_id"` + + // DefNetType + DefNetType string `json:"def_net_type"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // Dirty + Dirty bool `json:"dirty"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Lock status + LockStatus string `json:"lockStatus"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // RegisterComputes + RegisterComputes bool `json:"registerComputes"` + + // Resource limits + ResourceLimits ResourceLimits `json:"resourceLimits"` + + // Secret + Secret string `json:"secret"` + + // Status + Status string `json:"status"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // List of VINS IDs + VINS []uint64 `json:"vins"` + + // List of compute IDs + Computes []uint64 `json:"vms"` + + // List of resource types + ResTypes []string `json:"resTypes"` + + // UniqPools + UniqPools []string `json:"uniqPools"` +} + +// List of resource groups +type ListResourceGroups []RecordResourceGroup + +// Main information about Access Control List +type ItemACL struct { + // Explicit + Explicit bool `json:"explicit"` + + // GUID + GUID string `json:"guid"` + + // Right + Right string `json:"right"` + + // Status + Status string `json:"status"` + + // Type + Type string `json:"type"` + + // User group ID UserGroupID string `json:"userGroupId"` } +// List ACL +type ListACL []ItemACL + +// Resource limits type ResourceLimits struct { - CUC float64 `json:"CU_C"` - CUD float64 `json:"CU_D"` - CUI float64 `json:"CU_I"` - CUM float64 `json:"CU_M"` - CUNP float64 `json:"CU_NP"` + // CUC + CUC float64 `json:"CU_C"` + + // CUD + CUD float64 `json:"CU_D"` + + // CUI + CUI float64 `json:"CU_I"` + + // CUM + CUM float64 `json:"CU_M"` + + // CUNP + CUNP float64 `json:"CU_NP"` + + // GPU units GPUUnits float64 `json:"gpu_units"` } -type AffinityGroupCompute struct { - ComputeID uint64 `json:"computeId"` - OtherNode []uint64 `json:"otherNode"` - OtherNodeIndirect []uint64 `json:"otherNodeIndirect"` +// Main information about affinity group +type ItemAffinityGroup struct { + // Compute ID + ComputeID uint64 `json:"computeId"` + + // Other node + OtherNode []uint64 `json:"otherNode"` + + // Other node indirect + OtherNodeIndirect []uint64 `json:"otherNodeIndirect"` + + // Other node indirect soft OtherNodeIndirectSoft []uint64 `json:"otherNodeIndirectSoft"` - OtherNodeSoft []uint64 `json:"otherNodeSoft"` - SameNode []uint64 `json:"sameNode"` - SameNodeSoft []uint64 `json:"sameNodeSoft"` + + // Other node soft + OtherNodeSoft []uint64 `json:"otherNodeSoft"` + + // Same node + SameNode []uint64 `json:"sameNode"` + + // Same node soft + SameNodeSoft []uint64 `json:"sameNodeSoft"` } -type AffinityGroupComputeList []AffinityGroupCompute +// List of affinity groups +type ListAffinityGroups []ItemAffinityGroup -type Audit struct { - Call string `json:"call"` +// Main information about audit +type ItemAudit struct { + // Call + Call string `json:"call"` + + // Response time ResponseTime float64 `json:"responsetime"` - StatusCode uint64 `json:"statuscode"` - Timestamp float64 `json:"timestamp"` - User string `json:"user"` + + // Status code + StatusCode uint64 `json:"statuscode"` + + // Timestamp + Timestamp float64 `json:"timestamp"` + + // User + User string `json:"user"` } -type AuditList []Audit +// List of audits +type ListAudits []ItemAudit + +// Main information about compute +type ItemCompute struct { + // Account ID + AccountID uint64 `json:"accountId"` -type Compute struct { - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` + // Account name + AccountName string `json:"accountName"` + + // Affinity label AffinityLabel string `json:"affinityLabel"` - // TODO put actual type here - AffinityRules []any `json:"affinityRules"` + + // List of affinity rules + AffinityRules []interface{} `json:"affinityRules"` + + // Affinity weight AffinityWeight uint64 `json:"affinityWeight"` - // TODO put actual type here - AntiAffinityRules []any `json:"antiAffinityRules"` - CPUs uint64 `json:"cpus"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - ID uint64 `json:"id"` - Name string `json:"name"` - RAM uint64 `json:"ram"` - Registered bool `json:"registered"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - TotalDisksSize uint64 `json:"totalDisksSize"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - UserManaged bool `json:"userManaged"` - VINSConnected uint64 `json:"vinsConnected"` -} - -type ComputeList []Compute - -type LoadBalancer struct { - HAMode bool `json:"HAmode"` - ACL interface{} `json:"acl"` - Backends []Backend `json:"backends"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - Description string `json:"desc"` - DPAPIUser string `json:"dpApiUser"` - ExtNetID uint64 `json:"extnetId"` - Frontends []Frontend `json:"frontends"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - ImageID uint64 `json:"imageId"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - PrimaryNode Node `json:"primaryNode"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - SecondaryNode Node `json:"secondaryNode"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - VINSID uint64 `json:"vinsId"` -} - -type LoadBalancerDetailed struct { + + // List of anti affinity rules + AntiAffinityRules []interface{} `json:"antiAffinityRules"` + + // Number of CPU + CPUs uint64 `json:"cpus"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Number of RAM + RAM uint64 `json:"ram"` + + // Registered + Registered bool `json:"registered"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Total disks size + TotalDisksSize uint64 `json:"totalDisksSize"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // User managed + UserManaged bool `json:"userManaged"` + + // Number of ViNS connected + VINSConnected uint64 `json:"vinsConnected"` +} + +// List of computes +type ListComputes []ItemCompute + +// Main information about load balancer +type RecordLoadBalancer struct { + // HAMode + HAMode bool `json:"HAmode"` + + // Access Control List + ACL interface{} `json:"acl"` + + // List of Backends + Backends ListBackends `json:"backends"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // DPAPIUser + DPAPIUser string `json:"dpApiUser"` + + // External network ID + ExtNetID uint64 `json:"extnetId"` + + // List of frontends + Frontends ListFrontends `json:"frontends"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Image ID + ImageID uint64 `json:"imageId"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Primary node + PrimaryNode RecordNode `json:"primaryNode"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Secondary node + SecondaryNode RecordNode `json:"secondaryNode"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // VINS ID + VINSID uint64 `json:"vinsId"` +} + +// Detailed information about load balancer +type ItemLoadBalancer struct { + // DPAPI password DPAPIPassword string `json:"dpApiPassword"` - LoadBalancer + + // Main information about load balancer + RecordLoadBalancer } -type Backend struct { - Algorithm string `json:"algorithm"` - GUID string `json:"guid"` - Name string `json:"name"` - ServerDefaultSettings ServerSettings `json:"serverDefaultSettings"` - Servers []Server `json:"servers"` +// Main information about backend +type ItemBackend struct { + // Algorithm + Algorithm string `json:"algorithm"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` + + // Server settings + ServerDefaultSettings RecordServerSettings `json:"serverDefaultSettings"` + + // List of servers + Servers ListServers `json:"servers"` } -type LBList []LoadBalancerDetailed +// List of backends +type ListBackends []ItemBackend + +// List of load balancers +type ListLB []ItemLoadBalancer + +// Server settings +type RecordServerSettings struct { + // Inter + Inter uint64 `json:"inter"` -type ServerSettings struct { - Inter uint64 `json:"inter"` - GUID string `json:"guid"` + // GUID + GUID string `json:"guid"` + + // Down inter DownInter uint64 `json:"downinter"` - Rise uint64 `json:"rise"` - Fall uint64 `json:"fall"` + + // Rise + Rise uint64 `json:"rise"` + + // Fall + Fall uint64 `json:"fall"` + + // Slow start SlowStart uint64 `json:"slowstart"` - MaxConn uint64 `json:"maxconn"` - MaxQueue uint64 `json:"maxqueue"` - Weight uint64 `json:"weight"` + + // Max connections + MaxConn uint64 `json:"maxconn"` + + // Max queue + MaxQueue uint64 `json:"maxqueue"` + + // Weight + Weight uint64 `json:"weight"` } -type Server struct { - Address string `json:"address"` - Check string `json:"check"` - GUID string `json:"guid"` - Name string `json:"name"` - Port uint64 `json:"port"` - ServerSettings ServerSettings `json:"serverSettings"` +// Main information about server +type ItemServer struct { + // Address + Address string `json:"address"` + + // Check + Check string `json:"check"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` + + // Port + Port uint64 `json:"port"` + + // Server settings + ServerSettings RecordServerSettings `json:"serverSettings"` } -type Node struct { - BackendIP string `json:"backendIp"` - ComputeID uint64 `json:"computeId"` +// List of servers +type ListServers []ItemServer + +// Main information about node +type RecordNode struct { + // Backend IP + BackendIP string `json:"backendIp"` + + // Compute ID + ComputeID uint64 `json:"computeId"` + + // Frontend IP FrontendIP string `json:"frontendIp"` - GUID string `json:"guid"` - MGMTIP string `json:"mgmtIp"` - NetworkID uint64 `json:"networkId"` + + // GUID + GUID string `json:"guid"` + + // MGMT IP + MGMTIP string `json:"mgmtIp"` + + // Network ID + NetworkID uint64 `json:"networkId"` } -type Frontend struct { - Backend string `json:"backend"` - Bindings []Binding `json:"bindings"` - GUID string `json:"guid"` - Name string `json:"name"` +// Main information about frontend +type ItemFrontend struct { + // Backend + Backend string `json:"backend"` + + // List of bindings + Bindings ListBindings `json:"bindings"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` } -type Binding struct { +// List of frontends +type ListFrontends []ItemFrontend + +// Main information of binding +type ItemBinding struct { + // Address Address string `json:"address"` - GUID string `json:"guid"` - Name string `json:"name"` - Port uint64 `json:"port"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` + + // Port + Port uint64 `json:"port"` } -type PortForward struct { - PublicPortEnd uint64 `json:"Public Port End"` +// List of bindings +type ListBindings []ItemBinding + +// Main information about port forward +type ItemPortForward struct { + // Public port end + PublicPortEnd uint64 `json:"Public Port End"` + + // Public port start PublicPortStart uint64 `json:"Public Port Start"` - VMID uint64 `json:"VM ID"` - VMIP string `json:"VM IP"` - VMName string `json:"VM Name"` - VMPort uint64 `json:"VM Port"` - VINSID uint64 `json:"ViNS ID"` - VINSName string `json:"ViNS Name"` + + // Virtual machine ID + VMID uint64 `json:"VM ID"` + + // Virtual machine IP + VMIP string `json:"VM IP"` + + // Virtual machine name + VMName string `json:"VM Name"` + + // Virtual machine port + VMPort uint64 `json:"VM Port"` + + // VINS ID + VINSID uint64 `json:"ViNS ID"` + + // VINS name + VINSName string `json:"ViNS Name"` } -type PortForwardList []PortForward +// List of port forwards +type ListPortForwards []ItemPortForward + +// Main information about VINS +type ItemVINS struct { + // Account ID + AccountID uint64 `json:"accountId"` -type VINS struct { - AccountID uint64 `json:"accountId"` + // Account name AccountName string `json:"accountName"` - Computes uint64 `json:"computes"` - CreatedBy string `json:"createdBy"` + + // Computes + Computes uint64 `json:"computes"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time DeletedTime uint64 `json:"deletedTime"` - ExternalIP string `json:"externalIP"` - ID uint64 `json:"id"` - Name string `json:"name"` - Network string `json:"network"` + + // External IP + ExternalIP string `json:"externalIP"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Network + Network string `json:"network"` + + // PriVNFDev ID PriVNFDevID uint64 `json:"priVnfDevId"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - Status string `json:"status"` - UpdatedBy string `json:"updatedBy"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Status + Status string `json:"status"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time UpdatedTime uint64 `json:"updatedTime"` } -type VINSList []VINS +// List of VINSes +type ListVINS []ItemVINS -type ResourceUsage struct { - CPU uint64 `json:"cpu"` - DiskSize uint64 `json:"disksize"` - ExtIPs uint64 `json:"extips"` +// Main information about usage of resource +type RecordResourceUsage struct { + // Number of CPU + CPU uint64 `json:"cpu"` + + // Disk size + DiskSize uint64 `json:"disksize"` + + // Number of external IPs + ExtIPs uint64 `json:"extips"` + + // ExtraTraffic ExtraTraffic uint64 `json:"exttraffic"` - GPU uint64 `json:"gpu"` - RAM uint64 `json:"ram"` + + // Number of GPU + GPU uint64 `json:"gpu"` + + // Number of RAM + RAM uint64 `json:"ram"` } diff --git a/pkg/cloudapi/rg/restore.go b/pkg/cloudapi/rg/restore.go index da4e98c..e579b78 100644 --- a/pkg/cloudapi/rg/restore.go +++ b/pkg/cloudapi/rg/restore.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for restore resource group type RestoreRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq RestoreRequest) Validate() error { +func (rgrq RestoreRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } @@ -20,16 +26,24 @@ func (rgrq RestoreRequest) Validate() error { return nil } +// Restore restores resource group from recycle bin func (r RG) Restore(ctx context.Context, req RestoreRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/rg/restore" + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/rg/rg.go b/pkg/cloudapi/rg/rg.go index 52ed4f1..0aef1cf 100644 --- a/pkg/cloudapi/rg/rg.go +++ b/pkg/cloudapi/rg/rg.go @@ -1,13 +1,16 @@ +// API Actors for managing resource groups. These actors are the final API for end users to manage resource groups package rg import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to resource group type RG struct { client interfaces.Caller } +// Builder for resource group endpoints func New(client interfaces.Caller) *RG { return &RG{ client, diff --git a/pkg/cloudapi/rg/set_def_net.go b/pkg/cloudapi/rg/set_def_net.go index 46df0c0..208573f 100644 --- a/pkg/cloudapi/rg/set_def_net.go +++ b/pkg/cloudapi/rg/set_def_net.go @@ -9,18 +9,32 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for set default network type SetDefNetRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Network type + // Should be one of: + // - "PUBLIC" + // - "PRIVATE" + // Required: true NetType string `url:"netType"` - NetID uint64 `url:"netId"` - Reason string `url:"reason,omitempty"` + + // Network ID + // Required: false + NetID uint64 `url:"netId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` } -func (rgrq SetDefNetRequest) Validate() error { +func (rgrq SetDefNetRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } - if !validators.StringInSlice(rgrq.NetType, []string{"PUBLIC", "PRIVATE"}) { return errors.New("field NetType can only be one of 'PUBLIC' or 'PRIVATE'") } @@ -28,16 +42,24 @@ func (rgrq SetDefNetRequest) Validate() error { return nil } +// SetDefNet sets default network for attach associated virtual machines func (r RG) SetDefNet(ctx context.Context, req SetDefNetRequest) (uint64, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return 0, err } url := "/cloudapi/rg/setDefNet" + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return 0, err } - return strconv.ParseUint(string(res), 10, 64) + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil } diff --git a/pkg/cloudapi/rg/update.go b/pkg/cloudapi/rg/update.go index b287fc6..30abe7a 100644 --- a/pkg/cloudapi/rg/update.go +++ b/pkg/cloudapi/rg/update.go @@ -5,39 +5,98 @@ import ( "errors" "net/http" "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for update resource group type UpdateRequest struct { - RGID uint64 `url:"rgId"` - Name string `url:"name,omitempty"` - Desc string `url:"desc,omitempty"` - MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` - MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` - MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // New name + // Required: false + Name string `url:"name,omitempty"` + + // New description + // Required: false + Description string `url:"desc,omitempty"` + + // Max size of memory in MB + // Required: false + MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` + + // Max size of aggregated virtual disks in GB + // Required: false + MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` + + // Max number of CPU cores + // Required: false + MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + + // Max sent/received network transfer peering + // Required: false MaxNetworkPeerTransfer uint64 `url:"maxNetworkPeerTransfer,omitempty"` - MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"` - RegisterComputes bool `url:"registerComputes,omitempty"` - Reason string `url:"reason,omitempty"` + + // Max number of assigned public IPs + // Required: false + MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"` + + // Register computes in registration system + // Required: false + RegisterComputes bool `url:"registerComputes,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` + + // Resource types available to create in this account + // Each element in a resource type slice must be one of: + // - compute + // - vins + // - k8s + // - openshift + // - lb + // - flipgroup + // Required: false + ResTypes []string `url:"resourceTypes,omitempty"` } -func (rgrq UpdateRequest) Validate() error { +func (rgrq UpdateRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } + if len(rgrq.ResTypes) > 0 { + for _, value := range rgrq.ResTypes { + validate := validators.StringInSlice(value, []string{"compute", "vins", "k8s", "openshift", "lb", "flipgroup"}) + if !validate { + return errors.New("validation-error: Every resource type specified should be one of [compute, vins, k8s, openshift, lb, flipgroup]") + } + } + } return nil } +// Update updates resource group func (r RG) Update(ctx context.Context, req UpdateRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } url := "/cloudapi/rg/update" + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err } - return strconv.ParseBool(string(res)) + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil } diff --git a/pkg/cloudapi/rg/usage.go b/pkg/cloudapi/rg/usage.go index 98e25a3..fec6d63 100644 --- a/pkg/cloudapi/rg/usage.go +++ b/pkg/cloudapi/rg/usage.go @@ -7,12 +7,18 @@ import ( "net/http" ) +// Request struct for get report of resource usage type UsageRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq UsageRequest) Validate() error { +func (rgrq UsageRequest) validate() error { if rgrq.RGID == 0 { return errors.New("field RGID can not be empty or equal to 0") } @@ -20,21 +26,25 @@ func (rgrq UsageRequest) Validate() error { return nil } -func (r RG) Usage(ctx context.Context, req UpdateRequest) (*ResourceUsage, error) { - if err := req.Validate(); err != nil { +// Usage gets report resource usage on the resource group +func (r RG) Usage(ctx context.Context, req UsageRequest) (*RecordResourceUsage, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudapi/rg/usage" - usageRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - usage := &ResourceUsage{} - if err := json.Unmarshal(usageRaw, usage); err != nil { + info := RecordResourceUsage{} + err = json.Unmarshal(res, &info) + if err != nil { return nil, err } - return usage, nil + return &info, nil } diff --git a/pkg/cloudapi/sizes.go b/pkg/cloudapi/sizes.go index 59fdfac..25eb6b9 100644 --- a/pkg/cloudapi/sizes.go +++ b/pkg/cloudapi/sizes.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudapi/sizes" ) -func (ca *CloudApi) Sizes() *sizes.Sizes { +// Accessing the Sizes method group +func (ca *CloudAPI) Sizes() *sizes.Sizes { return sizes.New(ca.client) } diff --git a/pkg/cloudapi/sizes/list.go b/pkg/cloudapi/sizes/list.go index 2ee4811..26afa77 100644 --- a/pkg/cloudapi/sizes/list.go +++ b/pkg/cloudapi/sizes/list.go @@ -6,24 +6,40 @@ import ( "net/http" ) +// Request struct for list the available flavors type ListRequest struct { + // ID of the cloudspace + // Required: false CloudspaceID uint64 `url:"cloudspaceId,omitempty"` - Location string `url:"location,omitempty"` - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` + + // Location code for the sizes + // Required: false + Location string `url:"location,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (s Sizes) List(ctx context.Context, req ListRequest) (SizesList, error) { +// List gets list the available flavors, filtering can be based on the user which is doing the request +func (s Sizes) List(ctx context.Context, req ListRequest) (ListSizes, error) { url := "/cloudapi/sizes/list" - sizesListRaw, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - sizesList := SizesList{} - if err := json.Unmarshal(sizesListRaw, &sizesList); err != nil { + list := ListSizes{} + + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return sizesList, nil + return list, nil } diff --git a/pkg/cloudapi/sizes/models.go b/pkg/cloudapi/sizes/models.go index e50ee12..26f1de2 100644 --- a/pkg/cloudapi/sizes/models.go +++ b/pkg/cloudapi/sizes/models.go @@ -1,12 +1,25 @@ package sizes -type Size struct { - Description string `json:"desc"` - Disks []uint64 `json:"disks"` - ID uint64 `json:"id"` - Memory uint64 `json:"memory"` - Name string `json:"name"` - VCPUs uint64 `json:"vcpus"` +// Main onformation about configured available flavors +type ItemSize struct { + // Description + Description string `json:"desc"` + + // List of disk IDs + Disks []uint64 `json:"disks"` + + // ID + ID uint64 `json:"id"` + + // Memory + Memory uint64 `json:"memory"` + + // Name + Name string `json:"name"` + + // VCPUs + VCPUs uint64 `json:"vcpus"` } -type SizesList []Size +// List of configured available flavors +type ListSizes []ItemSize diff --git a/pkg/cloudapi/sizes/sizes.go b/pkg/cloudapi/sizes/sizes.go index ef63993..8f46aa8 100644 --- a/pkg/cloudapi/sizes/sizes.go +++ b/pkg/cloudapi/sizes/sizes.go @@ -1,13 +1,17 @@ +// Lists all the configured flavors available. +// A flavor is a combination of amount of compute capacity(CU) and disk capacity(GB). package sizes import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creatig request to sizes type Sizes struct { client interfaces.Caller } +// Builder for sizes endpoints func New(client interfaces.Caller) *Sizes { return &Sizes{ client, diff --git a/pkg/cloudapi/tasks.go b/pkg/cloudapi/tasks.go index 100ee71..471ff86 100644 --- a/pkg/cloudapi/tasks.go +++ b/pkg/cloudapi/tasks.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudapi/tasks" ) -func (ca *CloudApi) Tasks() *tasks.Tasks { +// Accessing the Tasks method group +func (ca *CloudAPI) Tasks() *tasks.Tasks { return tasks.New(ca.client) } diff --git a/pkg/cloudapi/tasks/get.go b/pkg/cloudapi/tasks/get.go index 3f9bf83..fb15576 100644 --- a/pkg/cloudapi/tasks/get.go +++ b/pkg/cloudapi/tasks/get.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get infromation about task type GetRequest struct { + // ID of audit + // Required: true AuditID string `url:"auditId"` } -func (trq GetRequest) Validate() error { +func (trq GetRequest) validate() error { if trq.AuditID == "" { return errors.New("validation-error: field AuditID can not be empty") } @@ -19,27 +22,27 @@ func (trq GetRequest) Validate() error { return nil } -func (t Tasks) Get(ctx context.Context, req GetRequest) (*AsyncTask, error) { - err := req.Validate() +// Get gets background API task status and result +func (t Tasks) Get(ctx context.Context, req GetRequest) (*RecordAsyncTask, error) { + err := req.validate() if err != nil { return nil, err } - url := "/tasks/get" - prefix := "/cloudapi" + url := "/cloudapi/tasks/get" - url = prefix + url - taskRaw, err := t.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := t.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - task := &AsyncTask{} - err = json.Unmarshal(taskRaw, task) + info := RecordAsyncTask{} + + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return task, nil + return &info, nil } diff --git a/pkg/cloudapi/tasks/list.go b/pkg/cloudapi/tasks/list.go index da77644..28f41d4 100644 --- a/pkg/cloudapi/tasks/list.go +++ b/pkg/cloudapi/tasks/list.go @@ -6,27 +6,33 @@ import ( "net/http" ) +// Request struct for get list of tasks type ListRequest struct { - Page uint64 `url:"page"` - Size uint64 `url:"size"` + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (t Tasks) List(ctx context.Context, req ListRequest) (TasksList, error) { - url := "/tasks/list" - prefix := "/cloudapi" +// List gets list user API tasks with status PROCESSING +func (t Tasks) List(ctx context.Context, req ListRequest) (ListTasks, error) { + url := "/cloudapi/tasks/list" - url = prefix + url - taskListRaw, err := t.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := t.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - taskList := TasksList{} - err = json.Unmarshal(taskListRaw, &taskList) + list := ListTasks{} + + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return taskList, nil + return list, nil } diff --git a/pkg/cloudapi/tasks/models.go b/pkg/cloudapi/tasks/models.go index 157aec6..8ea542b 100644 --- a/pkg/cloudapi/tasks/models.go +++ b/pkg/cloudapi/tasks/models.go @@ -6,8 +6,10 @@ import ( "strconv" ) +// Global variable for converting field to desired data type type TaskResult int +// Method for convert field func (r *TaskResult) UnmarshalJSON(b []byte) error { if b[0] == '"' { b := b[1 : len(b)-1] @@ -35,17 +37,35 @@ func (r *TaskResult) UnmarshalJSON(b []byte) error { return nil } -//AsyncTask represents a long task completion status -type AsyncTask struct { - AuditID string `json:"auditId"` - Completed bool `json:"completed"` - Error string `json:"error"` - Log []string `json:"log"` - Result TaskResult `json:"result"` - Stage string `json:"stage"` - Status string `json:"status"` - UpdateTime uint64 `json:"updateTime"` - UpdatedTime uint64 `json:"updatedTime"` +// Detailed information about task +type RecordAsyncTask struct { + // Audit ID + AuditID string `json:"auditId"` + + // Completed + Completed bool `json:"completed"` + + // Error + Error string `json:"error"` + + // List of logs + Log []string `json:"log"` + + // Final result + Result TaskResult `json:"result"` + + // Stage + Stage string `json:"stage"` + + // Status + Status string `json:"status"` + + // Update time + UpdateTime uint64 `json:"updateTime"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` } -type TasksList []AsyncTask +// List of tasks +type ListTasks []RecordAsyncTask diff --git a/pkg/cloudapi/tasks/tasks.go b/pkg/cloudapi/tasks/tasks.go index 9c0b5ff..9795b86 100644 --- a/pkg/cloudapi/tasks/tasks.go +++ b/pkg/cloudapi/tasks/tasks.go @@ -1,13 +1,16 @@ +// User API tasks interface package tasks import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to tasks type Tasks struct { client interfaces.Caller } +// Builder for tasks endpoints func New(client interfaces.Caller) *Tasks { return &Tasks{ client, diff --git a/pkg/cloudapi/vins.go b/pkg/cloudapi/vins.go index 9b25f5e..6ecc4d3 100644 --- a/pkg/cloudapi/vins.go +++ b/pkg/cloudapi/vins.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudapi/vins" ) -func (ca *CloudApi) VINS() *vins.VINS { +// Accessing the VINS method group +func (ca *CloudAPI) VINS() *vins.VINS { return vins.New(ca.client) } diff --git a/pkg/cloudapi/vins/audits.go b/pkg/cloudapi/vins/audits.go index 986fdc4..9d72c42 100644 --- a/pkg/cloudapi/vins/audits.go +++ b/pkg/cloudapi/vins/audits.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get audits type AuditsRequest struct { + // ID of the VINS + // Required: true VINSID uint64 `url:"vinsId"` } -func (vrq AuditsRequest) Validate() error { +func (vrq AuditsRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } @@ -19,25 +22,26 @@ func (vrq AuditsRequest) Validate() error { return nil } -func (v VINS) Audits(ctx context.Context, req AuditsRequest) (VINSAuditsList, error) { - err := req.Validate() +// Audits gets audit records for the specified VINS object +func (v VINS) Audits(ctx context.Context, req AuditsRequest) (ListAudits, error) { + err := req.validate() if err != nil { return nil, err } url := "/cloudapi/vins/audits" - auditsRaw, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - audits := VINSAuditsList{} + list := ListAudits{} - err = json.Unmarshal(auditsRaw, &audits) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return audits, nil + return list, nil } diff --git a/pkg/cloudapi/vins/create_in_account.go b/pkg/cloudapi/vins/create_in_account.go index bcccb3f..c5521e5 100644 --- a/pkg/cloudapi/vins/create_in_account.go +++ b/pkg/cloudapi/vins/create_in_account.go @@ -7,20 +7,37 @@ import ( "strconv" ) +// Request struct for create VINS in account type CreateInAccountRequest struct { - Name string `url:"name"` - AccountID uint64 `url:"accountId"` - GID uint64 `url:"gid,omitempty"` - IPCidr string `url:"ipcidr,omitempty"` - Description string `url:"desc,omitempty"` - PreReservationsNum uint `url:"preReservationsNum,omitempty"` + // VINS name + // Required: true + Name string `url:"name"` + + // ID of account + // Required: true + AccountID uint64 `url:"accountId"` + + // Grid ID + // Required: false + GID uint64 `url:"gid,omitempty"` + + // Private network IP CIDR + // Required: false + IPCIDR string `url:"ipcidr,omitempty"` + + // Description + // Required: false + Description string `url:"desc,omitempty"` + + // Number of pre created reservations + // Required: false + PreReservationsNum uint64 `url:"preReservationsNum,omitempty"` } -func (vrq CreateInAccountRequest) Validate() error { +func (vrq CreateInAccountRequest) validate() error { if vrq.Name == "" { return errors.New("validation-error: field Name can not be empty") } - if vrq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } @@ -28,8 +45,9 @@ func (vrq CreateInAccountRequest) Validate() error { return nil } +// CreateInAccount creates VINS in account level func (v VINS) CreateInAccount(ctx context.Context, req CreateInAccountRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } diff --git a/pkg/cloudapi/vins/create_in_rg.go b/pkg/cloudapi/vins/create_in_rg.go index 5aeed61..39c834a 100644 --- a/pkg/cloudapi/vins/create_in_rg.go +++ b/pkg/cloudapi/vins/create_in_rg.go @@ -7,21 +7,41 @@ import ( "strconv" ) +// Request struct for create VINS in resource group type CreateInRGRequest struct { - Name string `url:"name"` - RGID uint64 `url:"rgId"` - IPCidr string `url:"ipcidr,omitempty"` - ExtNetID uint64 `url:"extNetId,omitempty"` - ExtIP string `url:"extIp,omitempty"` - Description string `url:"desc,omitempty"` - PreReservationsNum uint `url:"preReservationsNum,omitempty"` + // VINS name + // Required: true + Name string `url:"name"` + + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Private network IP CIDR + // Required: false + IPCIDR string `url:"ipcidr,omitempty"` + + // External network ID + // Required: false + ExtNetID uint64 `url:"extNetId,omitempty"` + + // External IP, related only for extNetId >= 0 + // Required: false + ExtIP string `url:"extIp,omitempty"` + + // Description + // Required: false + Description string `url:"desc,omitempty"` + + // Number of pre created reservations + // Required: false + PreReservationsNum uint `url:"preReservationsNum,omitempty"` } -func (vrq CreateInRGRequest) Validate() error { +func (vrq CreateInRGRequest) validate() error { if vrq.Name == "" { return errors.New("validation-error: field Name can not be empty") } - if vrq.RGID == 0 { return errors.New("validation-error: field RGID can not be empty or equal to 0") } @@ -29,8 +49,9 @@ func (vrq CreateInRGRequest) Validate() error { return nil } +// CreateInRG creates VINS in resource group level func (v VINS) CreateInRG(ctx context.Context, req CreateInRGRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } diff --git a/pkg/cloudapi/vins/delete.go b/pkg/cloudapi/vins/delete.go index 3a1a55b..fd24430 100644 --- a/pkg/cloudapi/vins/delete.go +++ b/pkg/cloudapi/vins/delete.go @@ -7,13 +7,26 @@ import ( "strconv" ) +// Request struct for delete VINS type DeleteRequest struct { - VINSID uint64 `url:"vinsId"` - Force bool `url:"force"` - Permanently bool `url:"permanently"` + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Set to True if you want force delete non-empty VINS. + // Primarily, VINS is considered non-empty if it has virtual machines connected to it, + // and force flag will detach them from the VINS being deleted. + // Otherwise method will return an error + // Required: false + Force bool `url:"force,omitempty"` + + // Set to True if you want to destroy VINS and all linked resources, if any, immediately. + // Otherwise, they will be placed into recycle bin and could be restored later within the recycle bin's purge period + // Required: false + Permanently bool `url:"permanently,omitempty"` } -func (vrq DeleteRequest) Validate() error { +func (vrq DeleteRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } @@ -21,8 +34,9 @@ func (vrq DeleteRequest) Validate() error { return nil } +// Delete deletes VINS func (v VINS) Delete(ctx context.Context, req DeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/vins/disable_enable.go b/pkg/cloudapi/vins/disable_enable.go index c0aa12d..1595ff0 100644 --- a/pkg/cloudapi/vins/disable_enable.go +++ b/pkg/cloudapi/vins/disable_enable.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for disable/enable VINS type DisableEnableRequest struct { + // VINS ID + // Required: true VINSID uint64 `url:"vinsId"` } -func (vrq DisableEnableRequest) Validate() error { +func (vrq DisableEnableRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (vrq DisableEnableRequest) Validate() error { return nil } +// Disable disables VINS func (v VINS) Disable(ctx context.Context, req DisableEnableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -41,8 +45,9 @@ func (v VINS) Disable(ctx context.Context, req DisableEnableRequest) (bool, erro } +// Enable enables VINS func (v VINS) Enable(ctx context.Context, req DisableEnableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/vins/extnet_connect.go b/pkg/cloudapi/vins/extnet_connect.go index 806e365..e6b9c62 100644 --- a/pkg/cloudapi/vins/extnet_connect.go +++ b/pkg/cloudapi/vins/extnet_connect.go @@ -7,13 +7,22 @@ import ( "strconv" ) +// Request struct for connect external network type ExtNetConnectRequest struct { + // VINS ID + // Required: true VINSID uint64 `url:"vinsId"` - NetID uint64 `url:"netId"` - IP string `url:"ip"` + + // External network ID + // Required: false + NetID uint64 `url:"netId,omitempty"` + + // Directly set IP address + // Required: false + IP string `url:"ip,omitempty"` } -func (vrq ExtNetConnectRequest) Validate() error { +func (vrq ExtNetConnectRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } @@ -21,8 +30,9 @@ func (vrq ExtNetConnectRequest) Validate() error { return nil } +// ExtNetConnect connect VINS to external network func (v VINS) ExtNetConnect(ctx context.Context, req ExtNetConnectRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/vins/extnet_disconnect.go b/pkg/cloudapi/vins/extnet_disconnect.go index 5441ca2..0b0e573 100644 --- a/pkg/cloudapi/vins/extnet_disconnect.go +++ b/pkg/cloudapi/vins/extnet_disconnect.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for disconnect VINS from external network type ExtNetDisconnectRequest struct { + // VINS ID + // Required: true VINSID uint64 `url:"vinsId"` } -func (vrq ExtNetDisconnectRequest) Validate() error { +func (vrq ExtNetDisconnectRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (vrq ExtNetDisconnectRequest) Validate() error { return nil } +// ExtNetDisconnect disconnect VINS from external network func (v VINS) ExtNetDisconnect(ctx context.Context, req ExtNetDisconnectRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudapi/vins/extnet_list.go b/pkg/cloudapi/vins/extnet_list.go index 2a17bde..eceddc1 100644 --- a/pkg/cloudapi/vins/extnet_list.go +++ b/pkg/cloudapi/vins/extnet_list.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list VINS external network connections type ExtNetListRequest struct { + // VINS ID + // Required: true VINSID uint64 `url:"vinsId"` } -func (vrq ExtNetListRequest) Validate() error { +func (vrq ExtNetListRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } @@ -19,20 +22,27 @@ func (vrq ExtNetListRequest) Validate() error { return nil } -func (v VINS) ExtNetList(ctx context.Context, req ExtNetListRequest) (ExtNetList, error) { +// ExtNetList show list of VINS external network connections +func (v VINS) ExtNetList(ctx context.Context, req ExtNetListRequest) (ListExtNets, error) { + err := req.validate() + if err != nil { + return nil, err + } + url := "/cloudapi/vins/extNetList" - extnetListRaw, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - extnetList := ExtNetList{} - err = json.Unmarshal(extnetListRaw, &extnetList) + list := ListExtNets{} + + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return extnetList, nil + return list, nil } diff --git a/pkg/cloudapi/vins/get.go b/pkg/cloudapi/vins/get.go index 3a3161c..0fb222c 100644 --- a/pkg/cloudapi/vins/get.go +++ b/pkg/cloudapi/vins/get.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get information about VINS type GetRequest struct { + // VINS ID + // Required: true VINSID uint64 `url:"vinsId"` } -func (vrq GetRequest) Validate() error { +func (vrq GetRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (vrq GetRequest) Validate() error { return nil } -func (v VINS) Get(ctx context.Context, req GetRequest) (*VINSDetailed, error) { - err := req.Validate() +// Get gets information about VINS by ID +func (v VINS) Get(ctx context.Context, req GetRequest) (*RecordVINS, error) { + err := req.validate() if err != nil { return nil, err } @@ -32,13 +36,13 @@ func (v VINS) Get(ctx context.Context, req GetRequest) (*VINSDetailed, error) { return nil, err } - VINS := &VINSDetailed{} + info := RecordVINS{} - err = json.Unmarshal(res, VINS) + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return VINS, nil + return &info, nil } diff --git a/pkg/cloudapi/vins/ip_list.go b/pkg/cloudapi/vins/ip_list.go index 612d641..069fb73 100644 --- a/pkg/cloudapi/vins/ip_list.go +++ b/pkg/cloudapi/vins/ip_list.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for DHCP IP type IPListRequest struct { + // VINS ID + // Required: true VINSID uint64 `url:"vinsId"` } -func (vrq IPListRequest) Validate() error { +func (vrq IPListRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } @@ -19,25 +22,26 @@ func (vrq IPListRequest) Validate() error { return nil } -func (v VINS) IPList(ctx context.Context, req IPListRequest) (IPList, error) { - err := req.Validate() +// IPList show DHCP IP reservations on VINS +func (v VINS) IPList(ctx context.Context, req IPListRequest) (ListIPs, error) { + err := req.validate() if err != nil { return nil, err } url := "/cloudapi/vins/ipList" - ipListRaw, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - ipList := IPList{} - err = json.Unmarshal(ipListRaw, &ipList) + list := ListIPs{} + + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return ipList, nil - + return list, nil } diff --git a/pkg/cloudapi/vins/ip_release.go b/pkg/cloudapi/vins/ip_release.go index 4ed1679..9e8708a 100644 --- a/pkg/cloudapi/vins/ip_release.go +++ b/pkg/cloudapi/vins/ip_release.go @@ -7,13 +7,22 @@ import ( "strconv" ) +// Request struct for IP relese type IPReleaseRequest struct { + // VINS ID + // Required: true VINSID uint64 `url:"vinsId"` + + // IP address + // Required: false IPAddr string `url:"ipAddr,omitempty"` - MAC string `url:"mac,omitempty"` + + // MAC address + // Required: false + MAC string `url:"mac,omitempty"` } -func (vrq IPReleaseRequest) Validate() error { +func (vrq IPReleaseRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } @@ -21,8 +30,10 @@ func (vrq IPReleaseRequest) Validate() error { return nil } +// IPRelese delete IP reservation matched by specified IP & MAC address combination. +// If both IP and MAC address are empty strings, all IP reservations will be deleted. func (v VINS) IPRelese(ctx context.Context, req IPReleaseRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -40,5 +51,4 @@ func (v VINS) IPRelese(ctx context.Context, req IPReleaseRequest) (bool, error) } return result, nil - } diff --git a/pkg/cloudapi/vins/ip_reserve.go b/pkg/cloudapi/vins/ip_reserve.go index 6cac006..c6368db 100644 --- a/pkg/cloudapi/vins/ip_reserve.go +++ b/pkg/cloudapi/vins/ip_reserve.go @@ -4,30 +4,59 @@ import ( "context" "errors" "net/http" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for IP reserve type IPReserveRequest struct { - VINSID uint64 `url:"vinsId"` - Type string `url:"type"` - IPAddr string `url:"ipAddr,omitempty"` - MAC string `url:"mac,omitempty"` + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Type of the reservation + // Should be one of: + // - DHCP + // - VIP + // - EXCLUDE + // Required: true + Type string `url:"type"` + + // IP address to use. Non-empty string is required for type "EXCLUDE". + // Ignored for types "DHCP" and "VIP". + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // MAC address to associate with IP reservation. + // Ignored for type "EXCLUDE", + // non-empty string is required for "DHCP" and "VIP" + // Required: false + MAC string `url:"mac,omitempty"` + + // ID of the compute, associated with this reservation of type "DHCP". + // Ignored for other types + // Required: false ComputeID uint64 `url:"computeId,omitempty"` } -func (vrq IPReserveRequest) Validate() error { +func (vrq IPReserveRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } - if vrq.Type == "" { return errors.New("validation-error: field Type can not be empty") } + validate := validators.StringInSlice(vrq.Type, []string{"DHCP", "VIP", "EXCLUDED"}) + if !validate { + return errors.New("'type' should be 'DHCP', 'VIP' or 'EXCLUDED'") + } return nil } +// IPReserve creates reservation on ViNS DHCP func (v VINS) IPReserve(ctx context.Context, req IPReserveRequest) (string, error) { - err := req.Validate() + err := req.validate() if err != nil { return "", err } @@ -40,5 +69,4 @@ func (v VINS) IPReserve(ctx context.Context, req IPReserveRequest) (string, erro } return string(res), nil - } diff --git a/pkg/cloudapi/vins/list.go b/pkg/cloudapi/vins/list.go index 21af305..d607b11 100644 --- a/pkg/cloudapi/vins/list.go +++ b/pkg/cloudapi/vins/list.go @@ -6,26 +6,36 @@ import ( "net/http" ) +// Request struct for get list of VINSes type ListRequest struct { - IncludeDeleted bool `url:"includeDeleted"` - Page uint64 `url:"page"` - Size uint64 `url:"size"` + // Include deleted + // Required: false + IncludeDeleted bool `url:"includeDeleted,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (v VINS) List(ctx context.Context, req ListRequest) (VINSList, error) { +// List gets list of VINSes available for current user +func (v VINS) List(ctx context.Context, req ListRequest) (ListVINS, error) { url := "/cloudapi/vins/list" - VINSListRaw, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - VINSList := VINSList{} - err = json.Unmarshal(VINSListRaw, &VINSList) + list := ListVINS{} + + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return VINSList, nil - + return list, nil } diff --git a/pkg/cloudapi/vins/list_deleted.go b/pkg/cloudapi/vins/list_deleted.go index 67e9c1b..930952b 100644 --- a/pkg/cloudapi/vins/list_deleted.go +++ b/pkg/cloudapi/vins/list_deleted.go @@ -6,25 +6,32 @@ import ( "net/http" ) +// Request struct for get list of deleted VINSes type ListDeletedRequest struct { - Page uint64 `url:"page"` - Size uint64 `url:"size"` + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (v VINS) ListDeleted(ctx context.Context, req ListDeletedRequest) (VINSList, error) { +// ListDeleted gets list of deleted VINSes available for current user +func (v VINS) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListVINS, error) { url := "/cloudapi/vins/listDeleted" - VINSListRaw, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - VINSList := VINSList{} - err = json.Unmarshal(VINSListRaw, &VINSList) + list := ListVINS{} + + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return VINSList, nil - + return list, nil } diff --git a/pkg/cloudapi/vins/models.go b/pkg/cloudapi/vins/models.go index a91a718..8499474 100644 --- a/pkg/cloudapi/vins/models.go +++ b/pkg/cloudapi/vins/models.go @@ -1,271 +1,691 @@ package vins -type VINSRecord struct { - AccountID uint64 `json:"accountId"` +// Main information about VINS +type ItemVINS struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name AccountName string `json:"accountName"` - CreatedBy string `json:"createdBy"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time DeletedTime uint64 `json:"deletedTime"` - ExternalIP string `json:"externalIP"` - ID uint64 `json:"id"` - Name string `json:"name"` - Network string `json:"network"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - Status string `json:"status"` - UpdatedBy string `json:"updatedBy"` + + // External IP + ExternalIP string `json:"externalIP"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Network + Network string `json:"network"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Status + Status string `json:"status"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time UpdatedTime uint64 `json:"updatedTime"` - VXLANID uint64 `json:"vxlanId"` + + // VXLAN ID + VXLANID uint64 `json:"vxlanId"` } -type VINSList []VINSRecord +// List of VINSes +type ListVINS []ItemVINS -type VINSAudits struct { - Call string `json:"call"` +// Main information about audit +type ItemAudit struct { + // Call + Call string `json:"call"` + + // Response time ResponseTime float64 `json:"responsetime"` - StatusCode uint64 `json:"statuscode"` - Timestamp float64 `json:"timestamp"` - User string `json:"user"` + + // Status code + StatusCode uint64 `json:"statuscode"` + + // Timestamp + Timestamp float64 `json:"timestamp"` + + // User + User string `json:"user"` } -type VINSAuditsList []VINSAudits +// List of audits +type ListAudits []ItemAudit + +// Main information about external network +type ItemExtNet struct { + // Default GW + DefaultGW string `json:"default_gw"` + + // External network ID + ExtNetID uint64 `json:"ext_net_id"` + + // IP + IP string `json:"ip"` + + // Prefix len + PrefixLen uint64 `json:"prefixlen"` + + // Status + Status string `json:"status"` -type VINSExtNet struct { - DefaultGW string `json:"default_gw"` - ExtNetID uint64 `json:"ext_net_id"` - IP string `json:"ip"` - PrefixLen uint64 `json:"prefixlen"` - Status string `json:"status"` + // Tech status TechStatus string `json:"techStatus"` } -type ExtNetList []VINSExtNet +// List of external networks +type ListExtNets []ItemExtNet -type IP struct { +// Main information about IP +type ItemIP struct { + // Client type ClientType string `json:"clientType"` + + // Domain name DomainName string `json:"domainname"` - HostName string `json:"hostname"` - IP string `json:"ip"` - MAC string `json:"mac"` - Type string `json:"type"` - VMID uint64 `json:"vmId"` + + // Hostname + Hostname string `json:"hostname"` + + // IP + IP string `json:"ip"` + + // MAC + MAC string `json:"mac"` + + // Type + Type string `json:"type"` + + // Virtual machine ID + VMID uint64 `json:"vmId"` } -type IPList []IP - -type VNFDev struct { - CKey string `json:"_ckey"` - AccountID uint64 `json:"accountId"` - Capabilities []string `json:"capabilities"` - Config VNFConfig `json:"config"` - ConfigSaved bool `json:"configSaved"` - CustomPreConfig bool `json:"customPrecfg"` - Description string `json:"desc"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - Interfaces VNFInterfaceList `json:"interfaces"` - LockStatus string `json:"lockStatus"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - Type string `json:"type"` - VINS []uint64 `json:"vins"` +// List of IPs +type ListIPs []ItemIP + +// Main information about VNF device +type RecordVNFDev struct { + // CKey + CKey string `json:"_ckey"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Capabilities + Capabilities []string `json:"capabilities"` + + // Config + Config RecordVNFConfig `json:"config"` + + // Config saved + ConfigSaved bool `json:"configSaved"` + + // CustomPreConfig + CustomPreConfig bool `json:"customPrecfg"` + + // Description + Description string `json:"desc"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // List of interfaces + Interfaces ListVNFInterfaces `json:"interfaces"` + + // Lock status + LockStatus string `json:"lockStatus"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Type + Type string `json:"type"` + + // List of VINS IDs + VINS []uint64 `json:"vins"` } -type VNFConfig struct { - MGMT VNFConfigMGMT `json:"mgmt"` - Resources VNFConfigResources `json:"resources"` +// VNF config +type RecordVNFConfig struct { + // MGMT + MGMT RecordMGMT `json:"mgmt"` + + // Resources + Resources RecordResources `json:"resources"` } -type VNFConfigMGMT struct { - IPAddr string `json:"ipaddr"` +// Main information about MGMT +type RecordMGMT struct { + // IP address + IPAddress string `json:"ipaddr"` + + // Password Password string `json:"password"` - SSHKey string `json:"sshkey"` - User string `json:"user"` + + // SSH key + SSHKey string `json:"sshkey"` + + // User + User string `json:"user"` } -type VNFConfigResources struct { - CPU uint64 `json:"cpu"` - RAM uint64 `json:"ram"` +// Main information about resource +type RecordResources struct { + // Number of CPU + CPU uint64 `json:"cpu"` + + // Number of RAM + RAM uint64 `json:"ram"` + + // Stack ID StackID uint64 `json:"stackId"` - UUID string `json:"uuid"` + + // UUID + UUID string `json:"uuid"` } -type VNFInterface struct { - ConnID uint64 `json:"connId"` - ConnType string `json:"connType"` - DefGW string `json:"defGw"` - FlipGroupID uint64 `json:"flipgroupId"` - GUID string `json:"guid"` - IPAddress string `json:"ipAddress"` - ListenSSH bool `json:"listenSsh"` - MAC string `json:"mac"` - Name string `json:"name"` - NetID uint64 `json:"netId"` - NetMask uint64 `json:"netMask"` - NetType string `json:"netType"` - PCISlot uint64 `json:"pciSlot"` - QOS QOS `json:"qos"` - Target string `json:"target"` - Type string `json:"type"` - VNFS []uint64 `json:"vnfs"` +// Main information about VNF interface +type ItemVNFInterface struct { + // Connection ID + ConnID uint64 `json:"connId"` + + // Connection type + ConnType string `json:"connType"` + + // Default GW + DefGW string `json:"defGw"` + + // FLIPGroup ID + FLIPGroupID uint64 `json:"flipgroupId"` + + // GUID + GUID string `json:"guid"` + + // IP address + IPAddress string `json:"ipAddress"` + + // Listen SSH + ListenSSH bool `json:"listenSsh"` + + // MAC + MAC string `json:"mac"` + + // Name + Name string `json:"name"` + + // Network type + NetID uint64 `json:"netId"` + + // Network mask + NetMask uint64 `json:"netMask"` + + // Network type + NetType string `json:"netType"` + + // PCI slot + PCISlot uint64 `json:"pciSlot"` + + // QOS + QOS QOS `json:"qos"` + + // Target + Target string `json:"target"` + + // Type + Type string `json:"type"` + + // List of VNF IDs + VNFs []uint64 `json:"vnfs"` } +// Main information about QOS type QOS struct { - ERate uint64 `json:"eRate"` - GUID string `json:"guid"` + // ERate + ERate uint64 `json:"eRate"` + + // GUID + GUID string `json:"guid"` + + // InBurst InBurst uint64 `json:"inBurst"` - InRate uint64 `json:"inRate"` + + // InRate + InRate uint64 `json:"inRate"` } -type VNFInterfaceList []VNFInterface +// List of VNF interfaces +type ListVNFInterfaces []ItemVNFInterface + +// Main information about VINS compute +type ItemVINSCompute struct { + // ID + ID uint64 `json:"id"` -type VINSCompute struct { - ID uint64 `json:"id"` + // Name Name string `json:"name"` } -type VINSComputeList []VINSCompute +// List of VINS computes +type ListVINSComputes []ItemVINSCompute -type VNFS struct { - DHCP DHCP `json:"DHCP"` - GW GW `json:"GW"` - NAT NAT `json:"NAT"` +// Detailed information about VNF +type RecordVNFs struct { + // DHCP + DHCP RecordDHCP `json:"DHCP"` + + // GW + GW RecordGW `json:"GW"` + + // NAT + NAT RecordNAT `json:"NAT"` } -type NAT struct { - CKey string `json:"_ckey"` - AccountID uint64 `json:"accountId"` - CreatedTime uint64 `json:"createdTime"` - Devices Devices `json:"devices"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - LockStatus string `json:"lockStatus"` - Milestones uint64 `json:"milestones"` - OwnerID uint64 `json:"ownerId"` - OwnerType string `json:"ownerType"` - PureVirtual bool `json:"pureVirtual"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - Type string `json:"type"` +// Main information about NAT +type RecordNAT struct { + // CKey + CKey string `json:"_ckey"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Config + Config NATConfig `json:"config"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Detailed information about devices + Devices RecordDevices `json:"devices"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Lock status + LockStatus string `json:"lockStatus"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Owner ID + OwnerID uint64 `json:"ownerId"` + + // Owner type + OwnerType string `json:"ownerType"` + + // Pure virtual + PureVirtual bool `json:"pureVirtual"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Type + Type string `json:"type"` } +// NAT configuration type NATConfig struct { - NetMask uint64 `json:"netmask"` - Network string `json:"network"` - Rules []interface{} `json:"rules"` + // Network mask + NetMask uint64 `json:"netmask"` + + // Network + Network string `json:"network"` + + // List NAT rules + Rules ListNATRules `json:"rules"` } -type GW struct { - CKey string `json:"_ckey"` - AccountID uint64 `json:"accountId"` - Config GWConfig `json:"config"` - CreatedTime uint64 `json:"createdTime"` - Devices Devices `json:"devices"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - LockStatus string `json:"lockStatus"` - Milestones uint64 `json:"milestones"` - OwnerID uint64 `json:"ownerId"` - OwnerType string `json:"ownerType"` - PureVirtual bool `json:"pureVirtual"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - Type string `json:"type"` +// Main information about GW +type RecordGW struct { + // CKey + CKey string `json:"_ckey"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Config + Config RecordGWConfig `json:"config"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Detailed information about devices + Devices RecordDevices `json:"devices"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Lock status + LockStatus string `json:"lockStatus"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Owner ID + OwnerID uint64 `json:"ownerId"` + + // Owner type + OwnerType string `json:"ownerType"` + + // Pure virtual + PureVirtual bool `json:"pureVirtual"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Type + Type string `json:"type"` } -type GWConfig struct { - DefaultGW string `json:"default_gw"` - ExtNetID uint64 `json:"ext_net_id"` - ExtNetIP string `json:"ext_net_ip"` +// GW configuration +type RecordGWConfig struct { + // Default GW + DefaultGW string `json:"default_gw"` + + // External network ID + ExtNetID uint64 `json:"ext_net_id"` + + // External network IP + ExtNetIP string `json:"ext_net_ip"` + + // External network mask ExtNetMask uint64 `json:"ext_netmask"` - QOS QOS `json:"qos"` + + // QOS + QOS QOS `json:"qos"` } -type Devices struct { - Primary DevicePrimary `json:"primary"` +// Information about devices +type RecordDevices struct { + // Main information about primary device + Primary RecordPrimary `json:"primary"` } -type DevicePrimary struct { - DevID uint64 `json:"devId"` +// Main information about primary device +type RecordPrimary struct { + // Device ID + DevID uint64 `json:"devId"` + + // IFace01 IFace01 string `json:"iface01"` + + // IFace02 IFace02 string `json:"iface02"` } -type DHCP struct { - CKey string `json:"_ckey"` - AccountID uint64 `json:"accountId"` - Config DHCPConfig `json:"config"` - CreatedTime uint64 `json:"createdTime"` - Devices Devices `json:"devices"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - LockStatus string `json:"lockStatus"` - Milestones uint64 `json:"milestones"` - OwnerID uint64 `json:"ownerId"` - OwnerType string `json:"ownerType"` - PureVirtual bool `json:"pureVirtual"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - Type string `json:"type"` +// Main information about DHCP +type RecordDHCP struct { + // CKey + CKey string `json:"_ckey"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Config + Config RecordDHCPConfig `json:"config"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Detailed information about devices + Devices RecordDevices `json:"devices"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Lock status + LockStatus string `json:"lockStatus"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Owner ID + OwnerID uint64 `json:"ownerId"` + + // Owner type + OwnerType string `json:"ownerType"` + + // Pure virtual + PureVirtual bool `json:"pureVirtual"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Type + Type string `json:"type"` +} + +// DHCP configuration +type RecordDHCPConfig struct { + // Default GW + DefaultGW string `json:"default_gw"` + + // List of DNS + DNS []string `json:"dns"` + + // IP end + IPEnd string `json:"ip_end"` + + // IP start + IPStart string `json:"ip_start"` + + // Lease + Lease uint64 `json:"lease"` + + // Network mask + NetMask uint64 `json:"netmask"` + + // Network + Network string `json:"network"` + + // List of reservations + Reservations ListReservations `json:"reservations"` } -type DHCPConfig struct { - DefaultGW string `json:"default_gw"` - DNS []string `json:"dns"` - IPEnd string `json:"ip_end"` - IPStart string `json:"ip_start"` - Lease uint64 `json:"lease"` - Netmask uint64 `json:"netmask"` - Network string `json:"network"` - Reservations ReservationList `json:"reservations"` +// Detailed information about VINS +type RecordVINS struct { + // Main information about VNF device + VNFDev RecordVNFDev `json:"VNFDev"` + + // CKey + CKey string `json:"_ckey"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // List of VINS computes + Computes ListVINSComputes `json:"computes"` + + // Default GW + DefaultGW string `json:"defaultGW"` + + // Default QOS + DefaultQOS QOS `json:"defaultQos"` + + // Description + Description string `json:"desc"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Lock status + LockStatus string `json:"lockStatus"` + + // Manager ID + ManagerID uint64 `json:"managerId"` + + // Manager type + ManagerType string `json:"managerType"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Network mask + NetMask uint64 `json:"netMask"` + + // Network + Network string `json:"network"` + + // Pre reservaions number + PreReservaionsNum uint64 `json:"preReservationsNum"` + + // Redundant + Redundant bool `json:"redundant"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // SecVNFDevID + SecVNFDevID uint64 `json:"secVnfDevId"` + + // Status + Status string `json:"status"` + + // User managed + UserManaged bool `json:"userManaged"` + + // Main information about VNFs + VNFs RecordVNFs `json:"vnfs"` + + // VXLAN ID + VXLANID uint64 `json:"vxlanId"` } -type VINSDetailed struct { - VNFDev VNFDev `json:"VNFDev"` - CKey string `json:"_ckey"` - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - Computes VINSComputeList `json:"computes"` - DefaultGW string `json:"defaultGW"` - DefaultQOS QOS `json:"defaultQos"` - Description string `json:"desc"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - LockStatus string `json:"lockStatus"` - ManagerID uint64 `json:"managerId"` - ManagerType string `json:"managerType"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - NetMask uint64 `json:"netMask"` - Network string `json:"network"` - PreReservaionsNum uint64 `json:"preReservationsNum"` - Redundant bool `json:"redundant"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - SecVNFDevID uint64 `json:"secVnfDevId"` - Status string `json:"status"` - UserManaged bool `json:"userManaged"` - VNFS VNFS `json:"vnfs"` - VXLanID uint64 `json:"vxlanId"` +// Main information about NAT rule +type ItemNATRule struct { + // ID + ID uint64 `json:"id"` + + // Local IP + LocalIP string `json:"localIp"` + + // Local port + LocalPort uint64 `json:"localPort"` + + // Protocol + Protocol string `json:"protocol"` + + // Public port end + PublicPortEnd uint64 `json:"publicPortEnd"` + + // Public port start + PublicPortStart uint64 `json:"publicPortStart"` + + // Virtual machine ID + VMID uint64 `json:"vmId"` + + // Virtual machine name + VMName string `json:"vmName"` } -type Reservation struct { - ClientType string `json:"clientType"` +// List of NAT rules +type ListNATRules []ItemNATRule + +// Main information about reservation +type ItemReservation struct { + // Client type + ClientType string `json:"clientType"` + + // Description Description string `json:"desc"` - DomainName string `json:"domainname"` - HostName string `json:"hostname"` - IP string `json:"ip"` - MAC string `json:"mac"` - Type string `json:"type"` - VMID int `json:"vmId"` + + // Domain name + DomainName string `json:"domainname"` + + // Hostname + Hostname string `json:"hostname"` + + // IP + IP string `json:"ip"` + + // MAC + MAC string `json:"mac"` + + // Type + Type string `json:"type"` + + // Virtual machine ID + VMID uint64 `json:"vmId"` } -type ReservationList []Reservation +// List of reservations +type ListReservations []ItemReservation diff --git a/pkg/cloudapi/vins/nat_rule_add.go b/pkg/cloudapi/vins/nat_rule_add.go index d0acfae..02df2f3 100644 --- a/pkg/cloudapi/vins/nat_rule_add.go +++ b/pkg/cloudapi/vins/nat_rule_add.go @@ -7,28 +7,46 @@ import ( "strconv" ) -type NatRuleAddRequest struct { - VINSID uint64 `url:"vinsId"` - IntIP string `url:"intIp "` - IntPort uint `url:"intPort"` - ExtPortStart uint `url:"extPortStart"` - ExtPortEnd uint `url:"extPortEnd,omitempty"` - Proto string `url:"proto"` +// Request struct for create NAT rules +type NATRuleAddRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Internal IP address to apply this rule to + // Required: true + IntIP string `url:"intIp "` + + // Internal IP port number to use for this rule + // Required: true + IntPort uint `url:"intPort"` + + // External IP start port to use for this rule + // Required: true + ExtPortStart uint `url:"extPortStart"` + + // External IP end port to use for this rule + // Required: false + ExtPortEnd uint `url:"extPortEnd,omitempty"` + + // IP protocol type + // Should be one of: + // - "tcp" + // - "udp" + // Required: false + Proto string `url:"proto,omitempty"` } -func (vrq NatRuleAddRequest) Validate() error { +func (vrq NATRuleAddRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } - if vrq.IntIP == "" { return errors.New("validation-error: field IntIP can not be empty") } - if vrq.IntPort == 0 { return errors.New("validation-error: field IntPort can not be empty or equal to 0") } - if vrq.ExtPortStart == 0 { return errors.New("validation-error: field ExtPortStart can not be empty or equal to 0") } @@ -36,8 +54,9 @@ func (vrq NatRuleAddRequest) Validate() error { return nil } -func (v VINS) NatRuleAdd(ctx context.Context, req NatRuleAddRequest) (bool, error) { - err := req.Validate() +// NATRuleAdd create NAT (port forwarding) rule on VINS +func (v VINS) NATRuleAdd(ctx context.Context, req NATRuleAddRequest) (bool, error) { + err := req.validate() if err != nil { return false, err } @@ -55,5 +74,4 @@ func (v VINS) NatRuleAdd(ctx context.Context, req NatRuleAddRequest) (bool, erro } return result, nil - } diff --git a/pkg/cloudapi/vins/nat_rule_del.go b/pkg/cloudapi/vins/nat_rule_del.go index 5532d3a..9eba720 100644 --- a/pkg/cloudapi/vins/nat_rule_del.go +++ b/pkg/cloudapi/vins/nat_rule_del.go @@ -7,16 +7,22 @@ import ( "strconv" ) -type NatRuleDelRequest struct { +// Request struct for delete NAT rule +type NATRuleDelRequest struct { + // VINS ID + // Required: true VINSID uint64 `url:"vinsId"` + + // ID of the rule to delete. + // Pass -1 to clear all rules at once + // Required: true RuleID uint64 `url:"ruleId"` } -func (vrq NatRuleDelRequest) Validate() error { +func (vrq NATRuleDelRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } - if vrq.RuleID == 0 { return errors.New("validation-error: field RuleID can not be empty or equal to 0") } @@ -24,8 +30,9 @@ func (vrq NatRuleDelRequest) Validate() error { return nil } -func (v VINS) NatRuleDel(ctx context.Context, req NatRuleDelRequest) (bool, error) { - err := req.Validate() +// NATRuleDel delete NAT (port forwarding) rule on VINS +func (v VINS) NATRuleDel(ctx context.Context, req NATRuleDelRequest) (bool, error) { + err := req.validate() if err != nil { return false, err } @@ -43,5 +50,4 @@ func (v VINS) NatRuleDel(ctx context.Context, req NatRuleDelRequest) (bool, erro } return result, nil - } diff --git a/pkg/cloudapi/vins/nat_rule_list.go b/pkg/cloudapi/vins/nat_rule_list.go index 66bd1a0..b4afe9c 100644 --- a/pkg/cloudapi/vins/nat_rule_list.go +++ b/pkg/cloudapi/vins/nat_rule_list.go @@ -2,15 +2,19 @@ package vins import ( "context" + "encoding/json" "errors" "net/http" ) -type NatRuleListRequest struct { +// Request struct for get list of NAT rules +type NATRuleListRequest struct { + // VINS ID + // Required: true VINSID uint64 `url:"vinsId"` } -func (vrq NatRuleListRequest) Validate() error { +func (vrq NATRuleListRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } @@ -18,19 +22,26 @@ func (vrq NatRuleListRequest) Validate() error { return nil } -func (v VINS) NatRuleList(ctx context.Context, req NatRuleListRequest) (string, error) { - err := req.Validate() +// NATRuleList gets list of NAT (port forwarding) rules +func (v VINS) NATRuleList(ctx context.Context, req NATRuleListRequest) (ListNATRules, error) { + err := req.validate() if err != nil { - return "", err + return nil, err } url := "/cloudapi/vins/natRuleList" res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { - return "", err + return nil, err } - return string(res), nil + list := ListNATRules{} + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil } diff --git a/pkg/cloudapi/vins/restore.go b/pkg/cloudapi/vins/restore.go index 8a2b64c..a15f555 100644 --- a/pkg/cloudapi/vins/restore.go +++ b/pkg/cloudapi/vins/restore.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for restore type RestoreRequest struct { + // VINS ID + // Required: true VINSID uint64 `url:"vinsId"` } -func (vrq RestoreRequest) Validate() error { +func (vrq RestoreRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (vrq RestoreRequest) Validate() error { return nil } +// Restore restores VINS from recycle bin func (v VINS) Restore(ctx context.Context, req RestoreRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -38,5 +42,4 @@ func (v VINS) Restore(ctx context.Context, req RestoreRequest) (bool, error) { } return result, nil - } diff --git a/pkg/cloudapi/vins/search.go b/pkg/cloudapi/vins/search.go index e0b0bfb..3122c2c 100644 --- a/pkg/cloudapi/vins/search.go +++ b/pkg/cloudapi/vins/search.go @@ -6,27 +6,40 @@ import ( "net/http" ) +// Request struct for search VINSes type SearchRequest struct { + // ID of the account to search for the ViNSes + // Required: false AccountID uint64 `url:"accountId,omitempty"` - RGID uint64 `url:"rgId,omitempty"` - Name string `url:"name,omitempty"` - ShowAll bool `url:"show_all,omitempty"` + + // ID of the resource group to limit search to the specified RG level only + // Required: false + RGID uint64 `url:"rgId,omitempty"` + + // Name of the ViNS to search for + // Required: false + Name string `url:"name,omitempty"` + + // If False, then VINSes having one of the statuses are not listed for + // Required: false + ShowAll bool `url:"show_all,omitempty"` } -func (v VINS) Search(ctx context.Context, req SearchRequest) (VINSList, error) { +// Search search VINSes +func (v VINS) Search(ctx context.Context, req SearchRequest) (ListVINS, error) { url := "/cloudapi/vins/search" - VINSListRaw, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - VINSList := VINSList{} - err = json.Unmarshal(VINSListRaw, &VINSList) + list := ListVINS{} + + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return VINSList, nil - + return list, nil } diff --git a/pkg/cloudapi/vins/vins.go b/pkg/cloudapi/vins/vins.go index f7bed8f..0c59fc0 100644 --- a/pkg/cloudapi/vins/vins.go +++ b/pkg/cloudapi/vins/vins.go @@ -1,13 +1,16 @@ +// API Actor for managing VINS. This actor is a final API for endusers to manage VINS package vins import ( "github.com/rudecs/decort-sdk/interfaces" ) +// Structure for creating request to VINS type VINS struct { client interfaces.Caller } +// Builder for VINS endpoints func New(client interfaces.Caller) *VINS { return &VINS{ client, diff --git a/pkg/cloudapi/vins/vnfdev_redeploy.go b/pkg/cloudapi/vins/vnfdev_redeploy.go index dd58c4d..7fa6ef5 100644 --- a/pkg/cloudapi/vins/vnfdev_redeploy.go +++ b/pkg/cloudapi/vins/vnfdev_redeploy.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for redeploy VNFDevs type VNFDevRedeployRequest struct { + // VINS ID + // Required: true VINSID uint64 `url:"vinsId"` } -func (vrq VNFDevRedeployRequest) Validate() error { +func (vrq VNFDevRedeployRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (vrq VNFDevRedeployRequest) Validate() error { return nil } +// VNFDevRedeploy redeploy VINS VNFDevs func (v VINS) VNFDevRedeploy(ctx context.Context, req VNFDevRedeployRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -38,5 +42,4 @@ func (v VINS) VNFDevRedeploy(ctx context.Context, req VNFDevRedeployRequest) (bo } return result, nil - } diff --git a/pkg/cloudapi/vins/vnfdev_restart.go b/pkg/cloudapi/vins/vnfdev_restart.go index 105c2b4..d858d8a 100644 --- a/pkg/cloudapi/vins/vnfdev_restart.go +++ b/pkg/cloudapi/vins/vnfdev_restart.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for reboot VINSes primary VNF device type VNFDevRestartRequest struct { + // VINS ID + // Required: true VINSID uint64 `url:"vinsId"` } -func (vrq VNFDevRestartRequest) Validate() error { +func (vrq VNFDevRestartRequest) validate() error { if vrq.VINSID == 0 { return errors.New("validation-error: field VINSID can not be empty or equal to 0") } @@ -19,8 +22,9 @@ func (vrq VNFDevRestartRequest) Validate() error { return nil } +// VNFDevRestart reboot VINSes primary VNF device func (v VINS) VNFDevRestart(ctx context.Context, req VNFDevRestartRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -38,5 +42,4 @@ func (v VINS) VNFDevRestart(ctx context.Context, req VNFDevRestartRequest) (bool } return result, nil - } diff --git a/pkg/cloudbroker/account.go b/pkg/cloudbroker/account.go index e6124b7..97579a9 100644 --- a/pkg/cloudbroker/account.go +++ b/pkg/cloudbroker/account.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudbroker/account" ) +// Accessing the Account method group func (cb *CloudBroker) Account() *account.Account { return account.New(cb.client) } diff --git a/pkg/cloudbroker/account/account.go b/pkg/cloudbroker/account/account.go index d3ca99d..1fab6d8 100644 --- a/pkg/cloudbroker/account/account.go +++ b/pkg/cloudbroker/account/account.go @@ -1,11 +1,14 @@ +// API Actor API for managing account package account import "github.com/rudecs/decort-sdk/interfaces" +// Structure for creating request to account type Account struct { client interfaces.Caller } +// Builder for account endpoints func New(client interfaces.Caller) *Account { return &Account{ client: client, diff --git a/pkg/cloudbroker/account/add_user.go b/pkg/cloudbroker/account/add_user.go index c4988e2..b3d8fe6 100644 --- a/pkg/cloudbroker/account/add_user.go +++ b/pkg/cloudbroker/account/add_user.go @@ -9,35 +9,45 @@ import ( "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for adding permission to access to account for a user type AddUserRequest struct { - AccountID uint64 `url:"accountId"` - UserName string `url:"username"` + // ID of account to add to + // Required: true + AccountID uint64 `url:"accountId"` + + // Name of the user to be given rights + // Required: true + UserName string `url:"username"` + + // Account permission types: + // - 'R' for read only access + // - 'RCX' for Write + // - 'ARCXDU' for Admin + // Required: true AccessType string `url:"accesstype"` } -func (arq AddUserRequest) Validate() error { +func (arq AddUserRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } - if arq.UserName == "" { return errors.New("validation-error: field UserName can not be empty") } - if arq.AccessType == "" { return errors.New("validation-error: field AccessType can not be empty") } - - isValid := validators.StringInSlice(arq.AccessType, []string{"R", "RCX", "ARCXDU"}) - if !isValid { + validate := validators.StringInSlice(arq.AccessType, []string{"R", "RCX", "ARCXDU"}) + if !validate { return errors.New("validation-error: field AccessType can be only R, RCX or ARCXDU") } return nil } +// AddUser gives a user access rights. func (a Account) AddUser(ctx context.Context, req AddUserRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/account/audits.go b/pkg/cloudbroker/account/audits.go index 37d4edf..e1fa7d8 100644 --- a/pkg/cloudbroker/account/audits.go +++ b/pkg/cloudbroker/account/audits.go @@ -7,19 +7,23 @@ import ( "net/http" ) +// Request struct for give list account audits type AuditsRequest struct { + // ID of the account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq AuditsRequest) Validate() error { +func (arq AuditsRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID can not be empty or equal to 0") } return nil } -func (a Account) Audits(ctx context.Context, req AuditsRequest) (AccountAuditsList, error) { - err := req.Validate() +// Audits gets audit records for the specified account object +func (a Account) Audits(ctx context.Context, req AuditsRequest) (ListAudits, error) { + err := req.validate() if err != nil { return nil, err } @@ -30,11 +34,13 @@ func (a Account) Audits(ctx context.Context, req AuditsRequest) (AccountAuditsLi if err != nil { return nil, err } - result := AccountAuditsList{} - err = json.Unmarshal(res, &result) + + list := ListAudits{} + + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return result, nil + return list, nil } diff --git a/pkg/cloudbroker/account/create.go b/pkg/cloudbroker/account/create.go index 14c1f2a..a9d1f0e 100644 --- a/pkg/cloudbroker/account/create.go +++ b/pkg/cloudbroker/account/create.go @@ -5,34 +5,92 @@ import ( "errors" "net/http" "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for creating account type CreateRequest struct { - Name string `url:"name"` - Username string `url:"username"` - EmailAddress string `url:"emailaddress,omitempty"` - MaxMemoryCapacity uint `url:"maxMemoryCapacity,omitempty"` - MaxVDiskCapacity uint `url:"maxVDiskCapacity,omitempty"` - MaxCPUCapacity uint `url:"maxCPUCapacity,omitempty"` - MaxNetworkPeerTransfer uint `url:"maxNetworkPeerTransfer,omitempty"` - MaxNumPublicIP uint `url:"maxNumPublicIP,omitempty"` - SendAccessEmails bool `url:"sendAccessEmails,omitempty"` - GPUUnits uint `url:"gpu_units,omitempty"` + // Display name + // Required: true + Name string `url:"name"` + + // Name of the account + // Required: true + Username string `url:"username"` + + // Email + // Required: false + EmailAddress string `url:"emailaddress,omitempty"` + + // Max size of memory in MB + // Required: false + MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` + + // Max size of aggregated vdisks in GB + // Required: false + MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` + + // Max number of CPU cores + // Required: false + MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + + // Max sent/received network transfer peering + // Required: false + MaxNetworkPeerTransfer uint64 `url:"maxNetworkPeerTransfer,omitempty"` + + // Max number of assigned public IPs + // Required: false + MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"` + + // If true send emails when a user is granted access to resources + // Required: false + SendAccessEmails bool `url:"sendAccessEmails,omitempty"` + + // Limit (positive) or disable (0) GPU resources + // Required: false + GPUUnits uint64 `url:"gpu_units,omitempty"` + + // List of strings with pools + // i.e.: ["sep1_poolName1", "sep2_poolName2", etc] + // Required: false + UniqPools []string `url:"uniqPools,omitempty"` + + // Resource types available to create in this account + // Each element in a resource type slice must be one of: + // - compute + // - vins + // - k8s + // - openshift + // - lb + // - flipgroup + // Required: false + ResTypes []string `url:"resourceTypes,omitempty"` } -func (arq CreateRequest) Validate() error { +func (arq CreateRequest) validate() error { if arq.Name == "" { return errors.New("validation-error: field Name can not be empty") } - if arq.Username == "" { return errors.New("validation-error: field Username can not be empty") } + if len(arq.ResTypes) > 0 { + for _, value := range arq.ResTypes { + validate := validators.StringInSlice(value, []string{"compute", "vins", "k8s", "openshift", "lb", "flipgroup"}) + if !validate { + return errors.New("validation-error: Every resource type specified should be one of [compute, vins, k8s, openshift, lb, flipgroup]") + } + } + } + return nil } +// Create creates account +// Setting a cloud unit maximum to -1 or empty will not put any restrictions on the resource func (a Account) Create(ctx context.Context, req CreateRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } @@ -44,10 +102,10 @@ func (a Account) Create(ctx context.Context, req CreateRequest) (uint64, error) return 0, err } - id, err := strconv.ParseUint(string(res), 10, 64) + result, err := strconv.ParseUint(string(res), 10, 64) if err != nil { return 0, err } - return id, nil + return result, nil } diff --git a/pkg/cloudbroker/account/delete.go b/pkg/cloudbroker/account/delete.go index dd2cba3..69c4c28 100644 --- a/pkg/cloudbroker/account/delete.go +++ b/pkg/cloudbroker/account/delete.go @@ -6,24 +6,35 @@ import ( "net/http" ) +// Request struct for delete account type DeleteRequest struct { - AccountID uint64 `url:"accountId"` - Reason string `url:"reason"` - Permanently bool `url:"permanently,omitempty"` + // ID of account to delete + // Required: true + AccountID uint64 `url:"accountId"` + + // Reason to delete + // Required: true + Reason string `url:"reason"` + + // Whether to completely delete the account + // Required: false + Permanently bool `url:"permanently,omitempty"` } -func (arq DeleteRequest) Validate() error { +func (arq DeleteRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } if arq.Reason == "" { return errors.New("validation-error: field Reason must be set") } + return nil } +// Delete completes delete an account from the system Returns true if account is deleted or was already deleted or never existed func (a Account) Delete(ctx context.Context, req DeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/account/delete_accounts.go b/pkg/cloudbroker/account/delete_accounts.go index c19c940..88e152a 100644 --- a/pkg/cloudbroker/account/delete_accounts.go +++ b/pkg/cloudbroker/account/delete_accounts.go @@ -6,24 +6,35 @@ import ( "net/http" ) +// Request struct for delete group accounts type DeleteAccountsRequest struct { + // IDs of accounts + // Required: true AccountsIDs []uint64 `url:"accountIds"` - Reason string `url:"reason"` - Permanently bool `url:"permanently,omitempty"` + + // Reason for deletion + // Required: true + Reason string `url:"reason"` + + // Whether to completely destroy accounts or not + // Required: false + Permanently bool `url:"permanently,omitempty"` } -func (arq DeleteAccountsRequest) Validate() error { - if arq.AccountsIDs == nil || len(arq.AccountsIDs) == 0 { +func (arq DeleteAccountsRequest) validate() error { + if len(arq.AccountsIDs) == 0 { return errors.New("validation-error: field AccountIDs must be set") } if arq.Reason == "" { return errors.New("validation-error: field Reason must be set") } + return nil } +// DeleteAccounts destroy a group of accounts func (a Account) DeleteAccounts(ctx context.Context, req DeleteAccountsRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/account/delete_user.go b/pkg/cloudbroker/account/delete_user.go index 39e8e35..1fdad92 100644 --- a/pkg/cloudbroker/account/delete_user.go +++ b/pkg/cloudbroker/account/delete_user.go @@ -7,13 +7,22 @@ import ( "strconv" ) +// Request struct for revoke access to account type DeleteUserRequest struct { - AccountID uint64 `url:"accountId"` - UserName string `url:"username"` - RecursiveDelete bool `url:"recursivedelete,omitempty"` + // ID of the account + // Required: true + AccountID uint64 `url:"accountId"` + + // ID or emailaddress of the user to remove + // Required: true + UserName string `url:"username"` + + // Recursively revoke access rights from owned cloudspaces and vmachines + // Required: false + RecursiveDelete bool `url:"recursivedelete,omitempty"` } -func (arq DeleteUserRequest) Validate() error { +func (arq DeleteUserRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } @@ -24,8 +33,9 @@ func (arq DeleteUserRequest) Validate() error { return nil } +// DeleteUser revokes user access from the account func (a Account) DeleteUser(ctx context.Context, req DeleteUserRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -41,5 +51,6 @@ func (a Account) DeleteUser(ctx context.Context, req DeleteUserRequest) (bool, e if err != nil { return false, err } + return result, nil } diff --git a/pkg/cloudbroker/account/disable.go b/pkg/cloudbroker/account/disable.go index 4e06ad0..bf3f653 100644 --- a/pkg/cloudbroker/account/disable.go +++ b/pkg/cloudbroker/account/disable.go @@ -7,23 +7,31 @@ import ( "strconv" ) +// Request struct for disable account type DisableRequest struct { + // ID of account + // Required: true AccountID uint64 `url:"accountId"` - Reason string `url:"reason"` + + // Reason to disable + // Required: true + Reason string `url:"reason"` } -func (arq DisableRequest) Validate() error { +func (arq DisableRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } if arq.Reason == "" { return errors.New("validation-error: field Reason must be set") } + return nil } +// Disable disables an account func (a Account) Disable(ctx context.Context, req DisableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/account/disable_accounts.go b/pkg/cloudbroker/account/disable_accounts.go index 2c51f15..b00aa46 100644 --- a/pkg/cloudbroker/account/disable_accounts.go +++ b/pkg/cloudbroker/account/disable_accounts.go @@ -6,19 +6,24 @@ import ( "net/http" ) +// Request struct for disable group accounts type DisableAccountsRequest struct { + // IDs of accounts + // Required: true AccountIDs []uint64 `url:"accountIds,omitempty"` } -func (arq DisableAccountsRequest) Validate() error { - if arq.AccountIDs == nil || len(arq.AccountIDs) == 0 { +func (arq DisableAccountsRequest) validate() error { + if len(arq.AccountIDs) == 0 { return errors.New("validation-error: field AccountIDs must be set") } + return nil } +// DisableAccounts disables accounts func (a Account) DisableAccounts(ctx context.Context, req DisableAccountsRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/account/enable.go b/pkg/cloudbroker/account/enable.go index 77b38b7..aef14f8 100644 --- a/pkg/cloudbroker/account/enable.go +++ b/pkg/cloudbroker/account/enable.go @@ -7,23 +7,31 @@ import ( "strconv" ) +// Request struct for enable account type EnableRequest struct { + // ID of account + // Required: true AccountID uint64 `url:"accountId"` - Reason string `url:"reason"` + + // Reason to enable + // Required: true + Reason string `url:"reason"` } -func (arq EnableRequest) Validate() error { +func (arq EnableRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } if arq.Reason == "" { return errors.New("field Reason must be set") } + return nil } +// Enable enables an account func (a Account) Enable(ctx context.Context, req EnableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/account/enable_accounts.go b/pkg/cloudbroker/account/enable_accounts.go index 328c248..f962679 100644 --- a/pkg/cloudbroker/account/enable_accounts.go +++ b/pkg/cloudbroker/account/enable_accounts.go @@ -6,19 +6,24 @@ import ( "net/http" ) +// Request for enable group accounts type EnableAccountsRequest struct { + // IDs od accounts + // Required: true AccountIDs []uint64 `url:"accountIds"` } -func (arq EnableAccountsRequest) Validate() error { - if arq.AccountIDs == nil || len(arq.AccountIDs) == 0 { +func (arq EnableAccountsRequest) validate() error { + if len(arq.AccountIDs) == 0 { return errors.New("validation-error: field AccountIDs must be set") } + return nil } +// EnableAccounts enables accounts func (a Account) EnableAccounts(ctx context.Context, req EnableAccountsRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/account/get.go b/pkg/cloudbroker/account/get.go index c75a1de..84d0295 100644 --- a/pkg/cloudbroker/account/get.go +++ b/pkg/cloudbroker/account/get.go @@ -7,35 +7,41 @@ import ( "net/http" ) +// Request struct for get information about account type GetRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq GetRequest) Validate() error { +func (arq GetRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } + return nil } -func (a Account) Get(ctx context.Context, req GetRequest) (GetResponse, error) { - err := req.Validate() +// Get gets information about account +func (a Account) Get(ctx context.Context, req GetRequest) (*RecordAccount, error) { + err := req.validate() if err != nil { - return GetResponse{}, err + return nil, err } url := "/cloudbroker/account/get" - result := GetResponse{} + info := RecordAccount{} + res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { - return GetResponse{}, err + return nil, err } - err = json.Unmarshal(res, &result) + err = json.Unmarshal(res, &info) if err != nil { - return GetResponse{}, err + return nil, err } - return result, nil + return &info, nil } diff --git a/pkg/cloudbroker/account/list.go b/pkg/cloudbroker/account/list.go index 61a1225..f237954 100644 --- a/pkg/cloudbroker/account/list.go +++ b/pkg/cloudbroker/account/list.go @@ -6,23 +6,32 @@ import ( "net/http" ) +// Request struct for get list of accounts type ListRequest struct { - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` + // Page number + // Required: false + Page uint64 `url:"page"` + + // Page size + // Required: false + Size uint64 `url:"size"` } -func (a Account) List(ctx context.Context, req ListRequest) (ListInfoResponse, error) { +// List gets list all accounts the user has access to +func (a Account) List(ctx context.Context, req ListRequest) (ListAccounts, error) { url := "/cloudbroker/account/list" - result := ListInfoResponse{} res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { - return ListInfoResponse{}, err + return nil, err } - err = json.Unmarshal(res, &result) + + list := ListAccounts{} + + err = json.Unmarshal(res, &list) if err != nil { - return ListInfoResponse{}, err + return nil, err } - return result, nil + return list, nil } diff --git a/pkg/cloudbroker/account/list_computes.go b/pkg/cloudbroker/account/list_computes.go index e698498..996432c 100644 --- a/pkg/cloudbroker/account/list_computes.go +++ b/pkg/cloudbroker/account/list_computes.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for a get list compute instances type ListComputesRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq ListComputesRequest) Validate() error { +func (arq ListComputesRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } @@ -19,25 +22,26 @@ func (arq ListComputesRequest) Validate() error { return nil } +// ListComputes gets list all compute instances under specified account, accessible by the user func (a Account) ListComputes(ctx context.Context, req ListComputesRequest) (ListComputes, error) { - err := req.Validate() + err := req.validate() if err != nil { - return ListComputes{}, err + return nil, err } url := "/cloudbroker/account/listComputes" - result := ListComputes{} - res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { - return ListComputes{}, err + return nil, err } - err = json.Unmarshal(res, &result) + list := ListComputes{} + + err = json.Unmarshal(res, &list) if err != nil { - return ListComputes{}, err + return nil, err } - return result, nil + return list, nil } diff --git a/pkg/cloudbroker/account/list_deleted.go b/pkg/cloudbroker/account/list_deleted.go index 6e7b5ee..27a2fc7 100644 --- a/pkg/cloudbroker/account/list_deleted.go +++ b/pkg/cloudbroker/account/list_deleted.go @@ -6,24 +6,32 @@ import ( "net/http" ) +// Request struct for get list deleted accounts type ListDeletedRequest struct { - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` + // Page number + // Required: false + Page uint64 `url:"page"` + + // Page size + // Required: false + Size uint64 `url:"size"` } -func (a Account) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListInfoResponse, error) { +// ListDeleted gets list all deleted accounts the user has access to +func (a Account) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListAccounts, error) { url := "/cloudbroker/account/listDeleted" - result := ListInfoResponse{} res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { - return ListInfoResponse{}, err + return nil, err } - err = json.Unmarshal(res, &result) + list := ListAccounts{} + + err = json.Unmarshal(res, &list) if err != nil { - return ListInfoResponse{}, err + return nil, err } - return result, err + return list, nil } diff --git a/pkg/cloudbroker/account/list_disks.go b/pkg/cloudbroker/account/list_disks.go index f31328f..f5cc7b2 100644 --- a/pkg/cloudbroker/account/list_disks.go +++ b/pkg/cloudbroker/account/list_disks.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list deleted disks type ListDisksRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq ListDisksRequest) Validate() error { +func (arq ListDisksRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } @@ -19,25 +22,26 @@ func (arq ListDisksRequest) Validate() error { return nil } +// ListDisks gets list all currently unattached disks under specified account func (a Account) ListDisks(ctx context.Context, req ListDisksRequest) (ListDisks, error) { - err := req.Validate() + err := req.validate() if err != nil { - return ListDisks{}, err + return nil, err } url := "/cloudbroker/account/listDisks" - result := ListDisks{} - res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { - return ListDisks{}, err + return nil, err } - err = json.Unmarshal(res, &result) + list := ListDisks{} + + err = json.Unmarshal(res, &list) if err != nil { - return ListDisks{}, err + return nil, err } - return result, nil + return list, nil } diff --git a/pkg/cloudbroker/account/list_flip_groups.go b/pkg/cloudbroker/account/list_flip_groups.go index 2de4daf..a92ce48 100644 --- a/pkg/cloudbroker/account/list_flip_groups.go +++ b/pkg/cloudbroker/account/list_flip_groups.go @@ -7,11 +7,14 @@ import ( "net/http" ) -type ListFlipGroupsRequest struct { +// Request struct for get list FLIPGroups +type ListFLIPGroupsRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq ListFlipGroupsRequest) Validate() error { +func (arq ListFLIPGroupsRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } @@ -19,25 +22,26 @@ func (arq ListFlipGroupsRequest) Validate() error { return nil } -func (a Account) ListFlipGroups(ctx context.Context, req ListFlipGroupsRequest) (ListFlipGroups, error) { - err := req.Validate() +// ListFLIPGroups gets list all FLIPGroups under specified account, accessible by the user +func (a Account) ListFLIPGroups(ctx context.Context, req ListFLIPGroupsRequest) (ListFLIPGroups, error) { + err := req.validate() if err != nil { - return ListFlipGroups{}, err + return nil, err } url := "/cloudbroker/account/listFlipGroups" - result := ListFlipGroups{} - res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { - return ListFlipGroups{}, err + return nil, err } - err = json.Unmarshal(res, &result) + list := ListFLIPGroups{} + + err = json.Unmarshal(res, &list) if err != nil { - return ListFlipGroups{}, err + return nil, err } - return result, nil + return list, nil } diff --git a/pkg/cloudbroker/account/list_rg.go b/pkg/cloudbroker/account/list_rg.go index 4b6b881..83160fe 100644 --- a/pkg/cloudbroker/account/list_rg.go +++ b/pkg/cloudbroker/account/list_rg.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list resource groups type ListRGRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq ListRGRequest) Validate() error { +func (arq ListRGRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } @@ -19,25 +22,26 @@ func (arq ListRGRequest) Validate() error { return nil } +// ListRG gets list all resource groups under specified account, accessible by the user func (a Account) ListRG(ctx context.Context, req ListRGRequest) (ListRG, error) { - err := req.Validate() + err := req.validate() if err != nil { - return ListRG{}, err + return nil, err } url := "/cloudbroker/account/listRG" - result := ListRG{} - res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { - return ListRG{}, err + return nil, err } - err = json.Unmarshal(res, &result) + list := ListRG{} + + err = json.Unmarshal(res, &list) if err != nil { - return ListRG{}, err + return nil, err } - return result, nil + return list, nil } diff --git a/pkg/cloudbroker/account/list_vins.go b/pkg/cloudbroker/account/list_vins.go index d38e876..3f3e691 100644 --- a/pkg/cloudbroker/account/list_vins.go +++ b/pkg/cloudbroker/account/list_vins.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list VINS type ListVINSRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` } -func (arq ListVINSRequest) Validate() error { +func (arq ListVINSRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } @@ -19,25 +22,26 @@ func (arq ListVINSRequest) Validate() error { return nil } +// ListVINS gets list all ViNSes under specified account, accessible by the user func (a Account) ListVINS(ctx context.Context, req ListVINSRequest) (ListVINS, error) { - err := req.Validate() + err := req.validate() if err != nil { - return ListVINS{}, err + return nil, err } url := "/cloudbroker/account/listVins" - result := ListVINS{} - res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return ListVINS{}, err } - err = json.Unmarshal(res, &result) + list := ListVINS{} + + err = json.Unmarshal(res, &list) if err != nil { - return ListVINS{}, err + return nil, err } - return result, nil + return list, nil } diff --git a/pkg/cloudbroker/account/models.go b/pkg/cloudbroker/account/models.go index 32083ff..1809796 100644 --- a/pkg/cloudbroker/account/models.go +++ b/pkg/cloudbroker/account/models.go @@ -1,214 +1,500 @@ package account -type AccountAudit struct { - Call string `json:"call"` +// Main info about audit +type ItemAudit struct { + // Call + Call string `json:"call"` + + // Response time ResponseTime float64 `json:"responsetime"` - StatusCode uint64 `json:"statuscode"` - Timestamp float64 `json:"timestamp"` - User string `json:"user"` -} -type AccountAuditsList []AccountAudit + // Status code + StatusCode uint64 `json:"statuscode"` + + // Timestamp + Timestamp float64 `json:"timestamp"` -type Resources struct { - Current Current `json:"Current"` - Reserved Reserved `json:"Reserved"` + // User + User string `json:"user"` } -type Current struct { - CPU uint64 `json:"cpu"` - DiskSize uint64 `json:"disksize"` - ExtIPs uint64 `json:"extips"` - ExtTraffic uint64 `json:"exttraffic"` - GPU uint64 `json:"gpu"` - RAM uint64 `json:"ram"` +// List of audirs +type ListAudits []ItemAudit + +type RecordResources struct { + // Current information about resources + Current Resource `json:"Current"` + + // Reserved information about resources + Reserved Resource `json:"Reserved"` } -type Reserved struct { - CPU uint64 `json:"cpu"` - DiskSize uint64 `json:"disksize"` - ExtIPs uint64 `json:"extips"` - ExtTraffic uint64 `json:"exttraffic"` - GPU uint64 `json:"gpu"` - RAM uint64 `json:"ram"` +type Resource struct { + // Number of cores + CPU int64 `json:"cpu"` + + // Disk size + DiskSize int64 `json:"disksize"` + + // Number of External IPs + ExtIPs int64 `json:"extips"` + + // External traffic + ExtTraffic int64 `json:"exttraffic"` + + // Number of grafic cores + GPU int64 `json:"gpu"` + + // Number of RAM + RAM int64 `json:"ram"` } +// Access Control List type ACL struct { - Explicit bool `json:"explicit"` - GUID string `json:"guid"` - Right string `json:"right"` - Status string `json:"status"` - Type string `json:"type"` + // Whether access is explicitly specified + Explicit bool `json:"explicit"` + + // GUID + GUID string `json:"guid"` + + // Access rights + Right string `json:"right"` + + // Status + Status string `json:"status"` + + // Type + Type string `json:"type"` + + // User group ID UserGroupID string `json:"userGroupId"` } +// Resource limits type ResourceLimits struct { - CuC float64 `json:"CU_C"` - CuD float64 `json:"CU_D"` - CuI float64 `json:"CU_I"` - CuM float64 `json:"CU_M"` - CuNP float64 `json:"CU_NP"` + // CuC + CuC float64 `json:"CU_C"` + + // CuD + CuD float64 `json:"CU_D"` + + // CuI + CuI float64 `json:"CU_I"` + + // CuM + CuM float64 `json:"CU_M"` + + // CuNP + CuNP float64 `json:"CU_NP"` + + // GPUUnits GPUUnits float64 `json:"gpu_units"` } -type InfoResponse struct { - DCLocation string `json:"DCLocation"` - CKey string `json:"_ckey"` - ACL []ACL `json:"acl"` - Company string `json:"company"` - CompanyURL string `json:"companyurl"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeactivationTime float64 `json:"deactivationTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - DisplayName string `json:"displayname"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - Name string `json:"name"` - ResourceLimits ResourceLimits `json:"resourceLimits"` - SendAccessEmails bool `json:"sendAccessEmails"` - Status string `json:"status"` - UpdatedTime uint64 `json:"updatedTime"` - Version uint64 `json:"version"` - VINS []uint64 `json:"vins"` -} -type GetResponse struct { - Resources Resources `json:"Resources"` - InfoResponse -} - -type ListInfoResponse []struct { +// Main information about account +type InfoAccount struct { + // DCLocation + DCLocation string `json:"DCLocation"` + + // CKey + CKey string `json:"_ckey"` + + // Access Control List + ACL []ACL `json:"acl"` + + // Company + Company string `json:"company"` + + // Company URL + CompanyURL string `json:"companyurl"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deactivation time + DeactivationTime float64 `json:"deactivationTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Display name + DisplayName string `json:"displayname"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Resource limits + ResourceLimits ResourceLimits `json:"resourceLimits"` + + // Send access emails + SendAccessEmails bool `json:"sendAccessEmails"` + + // Status + Status string `json:"status"` + + // UpdatedTime + UpdatedTime uint64 `json:"updatedTime"` + + // Version + Version uint64 `json:"version"` + + // List of VINS IDs + VINS []uint64 `json:"vins"` +} + +// Deatailed information about account +type RecordAccount struct { + // Resources + Resources RecordResources `json:"Resources"` + + // Main information about account + InfoAccount +} + +// More information about account +type ItemAccount struct { + // Meta Meta []interface{} `json:"_meta"` - InfoResponse -} - -type ListComputes []Compute -type Compute struct { - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - CPUs uint64 `json:"cpus"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - ID uint64 `json:"id"` - Name string `json:"name"` - RAM uint64 `json:"ram"` - Registered bool `json:"registered"` - RgID uint64 `json:"rgId"` - RgName string `json:"rgName"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` + + // Main information about account + InfoAccount +} + +// List of accounts +type ListAccounts []ItemAccount + +// List of computes +type ListComputes []ItemCompute + +// Main information about compute +type ItemCompute struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Number of CPU + CPUs uint64 `json:"cpus"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Number of RAM + RAM uint64 `json:"ram"` + + // Registered + Registered bool `json:"registered"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RgName string `json:"rgName"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Total disks size TotalDisksSize uint64 `json:"totalDisksSize"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - UserManaged bool `json:"userManaged"` - VINSConnected uint64 `json:"vinsConnected"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // User managed + UserManaged bool `json:"userManaged"` + + // VINS Connected + VINSConnected uint64 `json:"vinsConnected"` } -type ListDisks []Disk +// List of disks +type ListDisks []ItemDisk + +// Main information about disks +type ItemDisk struct { + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Pool + Pool string `json:"pool"` -type Disk struct { - ID uint64 `json:"id"` - Name string `json:"name"` - Pool string `json:"pool"` - SepID uint64 `json:"sepId"` + // SepID + SepID uint64 `json:"sepId"` + + // Size max SizeMax uint64 `json:"sizeMax"` - Type string `json:"type"` + + // Type + Type string `json:"type"` } -type ListFlipGroups []FlipGroup +// List of FLIPGroups +type ListFLIPGroups []ItemFLIPGroup + +// Main information about FLIPGroup +type ItemFLIPGroup struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Client type + ClientType string `json:"clientType"` + + // Connection type + ConnType string `json:"connType"` -type FlipGroup struct { - AccountID uint64 `json:"accountId"` - ClientType string `json:"clientType"` - ConnType string `json:"connType"` - CreatedBy string `json:"createdBy"` + // Created by + CreatedBy string `json:"createdBy"` + + // Created time CreatedTime uint64 `json:"createdTime"` - DefaultGW string `json:"defaultGW"` - DeletedBy string `json:"deletedBy"` + + // Default GW + DefaultGW string `json:"defaultGW"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time DeletedTime uint64 `json:"deletedTime"` - Desc string `json:"desc"` - Gid uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - IP string `json:"ip"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - NetID uint64 `json:"netId"` - NetType string `json:"netType"` - Netmask uint64 `json:"netmask"` - Status string `json:"status"` - UpdatedBy string `json:"updatedBy"` + + // Description + Description string `json:"desc"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // IP + IP string `json:"ip"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Network ID + NetID uint64 `json:"netId"` + + // Network type + NetType string `json:"netType"` + + // Network mask + Netmask uint64 `json:"netmask"` + + // Status + Status string `json:"status"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time UpdatedTime uint64 `json:"updatedTime"` } +// Computes info type Computes struct { + // Started Started uint64 `json:"Started"` + + // Stopped Stopped uint64 `json:"Stopped"` } +// Consumed type Consumed struct { - CPU uint64 `json:"cpu"` - DiskSize uint64 `json:"disksize"` - ExtIPs uint64 `json:"extips"` + // Number of CPU + CPU uint64 `json:"cpu"` + + // Disk size + DiskSize uint64 `json:"disksize"` + + // External IPs + ExtIPs uint64 `json:"extips"` + + // External traffic ExtTraffic uint64 `json:"exttraffic"` - GPU uint64 `json:"gpu"` - RAM uint64 `json:"ram"` + + // Number of GPU + GPU uint64 `json:"gpu"` + + // Number of RAM + RAM uint64 `json:"ram"` } +// Limits type Limits struct { - CPU int64 `json:"cpu"` - DiskSize int64 `json:"disksize"` - ExtIPs int64 `json:"extips"` + // Number of CPU + CPU int64 `json:"cpu"` + + // Disk size + DiskSize int64 `json:"disksize"` + + // External IPs + ExtIPs int64 `json:"extips"` + + // External traffic ExtTraffic int64 `json:"exttraffic"` - GPU int64 `json:"gpu"` - RAM int64 `json:"ram"` + + // Number of GPU + GPU int64 `json:"gpu"` + + // Number of RAM + RAM int64 `json:"ram"` } +// Resources of resource group type RGResuorces struct { + // Consumed Consumed Consumed `json:"Consumed"` - Limits Limits `json:"Limits"` - Reserved Reserved `json:"Reserved"` -} - -type RG struct { - Computes Computes `json:"Computes"` - Resources RGResuorces `json:"Resources"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - ID uint64 `json:"id"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - Status string `json:"status"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - VINSes uint64 `json:"vinses"` -} - -type ListRG []RG - -type VINS struct { - AccountID uint64 `json:"accountId"` + + // Limits + Limits Limits `json:"Limits"` + + // Reserved + Reserved Resource `json:"Reserved"` +} + +// Main information about Resource group +type ItemRG struct { + // Compute + Computes Computes `json:"Computes"` + + // Resources of resource group + Resources RGResuorces `json:"Resources"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // ID + ID uint64 `json:"id"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Status + Status string `json:"status"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // Number of VINSes + VINSes uint64 `json:"vinses"` +} + +// List of resource groups +type ListRG []ItemRG + +// Main information about VINS +type ItemVINS struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name AccountName string `json:"accountName"` - Computes uint64 `json:"computes"` - CreatedBy string `json:"createdBy"` + + // Computes + Computes uint64 `json:"computes"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time DeletedTime uint64 `json:"deletedTime"` - ExternalIP string `json:"externalIP"` - ID uint64 `json:"id"` - Name string `json:"name"` - Network string `json:"network"` - PriVnfDevID uint64 `json:"priVnfDevId"` - RgID uint64 `json:"rgId"` - RgName string `json:"rgName"` - Status string `json:"status"` - UpdatedBy string `json:"updatedBy"` + + // External IP + ExternalIP string `json:"externalIP"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Network + Network string `json:"network"` + + // PriVNFDevID + PriVNFDevID uint64 `json:"priVnfDevId"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Status + Status string `json:"status"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time UpdatedTime uint64 `json:"updatedTime"` } -type ListVINS []VINS +// List of VINSes +type ListVINS []ItemVINS diff --git a/pkg/cloudbroker/account/restore.go b/pkg/cloudbroker/account/restore.go index a4ffa4f..4c67643 100644 --- a/pkg/cloudbroker/account/restore.go +++ b/pkg/cloudbroker/account/restore.go @@ -6,12 +6,18 @@ import ( "net/http" ) +// Request struct for restore a deleted account type RestoreRequest struct { + // ID an account + // Required: true AccountID uint64 `url:"accountId"` - Reason string `url:"reason"` + + // Reason to restore + // Required: true + Reason string `url:"reason"` } -func (arq RestoreRequest) Validate() error { +func (arq RestoreRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } @@ -22,8 +28,9 @@ func (arq RestoreRequest) Validate() error { return nil } +// Restore restores a deleted account func (a Account) Restore(ctx context.Context, req RestoreRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -36,4 +43,4 @@ func (a Account) Restore(ctx context.Context, req RestoreRequest) (bool, error) } return true, nil -} \ No newline at end of file +} diff --git a/pkg/cloudbroker/account/update.go b/pkg/cloudbroker/account/update.go index e84da49..7b3af9d 100644 --- a/pkg/cloudbroker/account/update.go +++ b/pkg/cloudbroker/account/update.go @@ -5,33 +5,95 @@ import ( "errors" "net/http" "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for update account type UpdateRequest struct { - AccountID uint64 `url:"accountId"` - Name string `url:"name"` - MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` - MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` - MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + // ID of account + // Required: true + AccountID uint64 `url:"accountId"` + + // Display name + // Required: true + Name string `url:"name"` + + // Name of the account + // Required: true + Username string `url:"username"` + + // Email + // Required: false + EmailAddress string `url:"emailaddress,omitempty"` + + // Max size of memory in MB + // Required: false + MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` + + // Max size of aggregated vdisks in GB + // Required: false + MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` + + // Max number of CPU cores + // Required: false + MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + + // Max sent/received network transfer peering + // Required: false MaxNetworkPeerTransfer uint64 `url:"maxNetworkPeerTransfer,omitempty"` - MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"` - SendAccessEmails bool `url:"sendAccessEmails,omitempty"` - GPUUnits uint64 `url:"gpu_units,omitempty"` + + // Max number of assigned public IPs + // Required: false + MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"` + + // If true send emails when a user is granted access to resources + // Required: false + SendAccessEmails bool `url:"sendAccessEmails,omitempty"` + + // Limit (positive) or disable (0) GPU resources + // Required: false + GPUUnits uint64 `url:"gpu_units,omitempty"` + + // List of strings with pools + // i.e.: ["sep1_poolName1", "sep2_poolName2", etc] + // Required: false + UniqPools []string `url:"uniqPools,omitempty"` + + // Resource types available to create in this account + // Each element in a resource type slice must be one of: + // - compute + // - vins + // - k8s + // - openshift + // - lb + // - flipgroup + // Required: false + ResTypes []string `url:"resourceTypes,omitempty"` } -func (arq UpdateRequest) Validate() error { +func (arq UpdateRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } if arq.Name == "" { return errors.New("validation-error: field Name must be set") } + if len(arq.ResTypes) > 0 { + for _, value := range arq.ResTypes { + validate := validators.StringInSlice(value, []string{"compute", "vins", "k8s", "openshift", "lb", "flipgroup"}) + if !validate { + return errors.New("validation-error: Every resource type specified should be one of [compute, vins, k8s, openshift, lb, flipgroup]") + } + } + } return nil } +// Update updates an account name and resource types and limits func (a Account) Update(ctx context.Context, req UpdateRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/account/update_user.go b/pkg/cloudbroker/account/update_user.go index ac689ce..2b195fb 100644 --- a/pkg/cloudbroker/account/update_user.go +++ b/pkg/cloudbroker/account/update_user.go @@ -7,13 +7,25 @@ import ( "strconv" ) +// Request struct for update user access rights type UpdateUserRequest struct { - AccountID uint64 `url:"accountId"` - UserID string `url:"userId"` + // ID of the account + // Required: true + AccountID uint64 `url:"accountId"` + + // Userid/Email for registered users or emailaddress for unregistered users + // Required: true + UserID string `url:"userId"` + + // Account permission types: + // - 'R' for read only access + // - 'RCX' for Write + // - 'ARCXDU' for Admin + // Required: true AccessType string `url:"accesstype"` } -func (arq UpdateUserRequest) Validate() error { +func (arq UpdateUserRequest) validate() error { if arq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } @@ -27,8 +39,9 @@ func (arq UpdateUserRequest) Validate() error { return nil } +// UpdateUser updates user access rights func (a Account) UpdateUser(ctx context.Context, req UpdateUserRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/cloudbroker.go b/pkg/cloudbroker/cloudbroker.go index bec0e1f..0810fdc 100644 --- a/pkg/cloudbroker/cloudbroker.go +++ b/pkg/cloudbroker/cloudbroker.go @@ -1,11 +1,14 @@ +// List of method groups for the admin package cloudbroker import "github.com/rudecs/decort-sdk/interfaces" +// Structure for creating request to CloudBroker groups type CloudBroker struct { client interfaces.Caller } +// Builder to get access to CloudBroker func New(client interfaces.Caller) *CloudBroker { return &CloudBroker{ client: client, diff --git a/pkg/cloudbroker/compute.go b/pkg/cloudbroker/compute.go index 24d2b11..7a6e745 100644 --- a/pkg/cloudbroker/compute.go +++ b/pkg/cloudbroker/compute.go @@ -1,9 +1,10 @@ package cloudbroker import ( - "github.com/rudecs/decort-sdk/pkg/cloudapi/compute" + "github.com/rudecs/decort-sdk/pkg/cloudbroker/compute" ) +// Accessing the Compute method group func (cb *CloudBroker) Compute() *compute.Compute { return compute.New(cb.client) } diff --git a/pkg/cloudbroker/compute/affinity_group_check_start.go b/pkg/cloudbroker/compute/affinity_group_check_start.go new file mode 100644 index 0000000..f039ec4 --- /dev/null +++ b/pkg/cloudbroker/compute/affinity_group_check_start.go @@ -0,0 +1,46 @@ +package compute + +import ( + "context" + "errors" + "net/http" +) + +// Request struct for check all computes with current affinity label can start +type AffinityGroupCheckStartRequest struct { + // ID of the resource group + // Required: true + RGID uint64 `url:"rgId"` + + // Affinity group label + // Required: true + AffinityLabel string `url:"affinityLabel"` +} + +func (crq AffinityGroupCheckStartRequest) validate() error { + if crq.RGID == 0 { + return errors.New("validation-error: field RGID must be set") + } + if crq.AffinityLabel == "" { + return errors.New("validation-error: field AffinityLabel must be set") + } + + return nil +} + +// AffinityGroupCheckStart check all computes with current affinity label can start +func (c Compute) AffinityGroupCheckStart(ctx context.Context, req AffinityGroupCheckStartRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/compute/affinityGroupCheckStart" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + return string(res), nil +} diff --git a/pkg/cloudbroker/compute/affinity_label_remove.go b/pkg/cloudbroker/compute/affinity_label_remove.go new file mode 100644 index 0000000..b7684d1 --- /dev/null +++ b/pkg/cloudbroker/compute/affinity_label_remove.go @@ -0,0 +1,45 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for clear affinity label for compute +type AffinityLabelRemoveRequest struct { + // IDs of the compute instances + // Required: true + ComputeIDs []uint64 `url:"computeIds"` +} + +func (crq AffinityLabelRemoveRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// AffinityLabelRemove clear affinity label for compute +func (c Compute) AffinityLabelRemove(ctx context.Context, req AffinityLabelRemoveRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/affinityLabelRemove" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/affinity_label_set.go b/pkg/cloudbroker/compute/affinity_label_set.go new file mode 100644 index 0000000..07bc742 --- /dev/null +++ b/pkg/cloudbroker/compute/affinity_label_set.go @@ -0,0 +1,51 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for set affinity label for compute +type AffinityLabelSetRequest struct { + // IDs of the compute instances + ComputeIDs []uint64 `url:"computeIds"` + + // Affinity group label + // Required: true + AffinityLabel string `url:"affinityLabel"` +} + +func (crq AffinityLabelSetRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeIDs must be set") + } + if crq.AffinityLabel == "" { + return errors.New("validation-error: field AffinityLabel must be set") + } + + return nil +} + +// AffinityLabelSet set affinity label for compute +func (c Compute) AffinityLabelSet(ctx context.Context, req AffinityLabelSetRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/affinityLabelSet" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/affinity_relations.go b/pkg/cloudbroker/compute/affinity_relations.go new file mode 100644 index 0000000..a5dd866 --- /dev/null +++ b/pkg/cloudbroker/compute/affinity_relations.go @@ -0,0 +1,51 @@ +package compute + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get dict of computes +type AffinityRelationsRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Affinity group label + // Required: false + AffinityLabel string `url:"affinityLabel,omitempty"` +} + +func (crq AffinityRelationsRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID can not be empty or equal to 0") + } + + return nil +} + +// AffinityRelations gets dict of computes divided by affinity and anti affinity rules +func (c Compute) AffinityRelations(ctx context.Context, req AffinityRelationsRequest) (*RecordAffinityRelations, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/compute/affinityRelations" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + info := RecordAffinityRelations{} + + err = json.Unmarshal(res, &info) + if err != nil { + return nil, err + } + + return &info, nil +} diff --git a/pkg/cloudbroker/compute/affinity_rule_add.go b/pkg/cloudbroker/compute/affinity_rule_add.go new file mode 100644 index 0000000..1e77325 --- /dev/null +++ b/pkg/cloudbroker/compute/affinity_rule_add.go @@ -0,0 +1,103 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" +) + +// Request struct for add affinity rule +type AffinityRuleAddRequest struct { + // IDs of the compute instances + // Required: true + ComputeIDs []uint64 `url:"computeIds"` + + // Should be one of: + // - node + // - compute + // Required: true + Topology string `url:"topology"` + + // The degree of 'strictness' of this rule + // Should be one of: + // - RECOMMENDED + // - REQUIRED + // Required: true + Policy string `url:"policy"` + + // The comparison mode is 'value', recorded by the specified 'key' + // Should be one of: + // - EQ + // - EN + // - ANY + // Required: true + Mode string `url:"mode"` + + // Key that are taken into account when analyzing this rule will be identified + // Required: true + Key string `url:"key"` + + // Value that must match the key to be taken into account when analyzing this rule + // Required: true + Value string `url:"value"` +} + +func (crq AffinityRuleAddRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeIDs must be set") + } + if crq.Topology == "" { + return errors.New("validation-error: field Topology must be set") + } + validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"}) + if !validator { + return errors.New("validation-error: field Topology can be only compute or node") + } + if crq.Policy == "" { + return errors.New("validation-error: field Policy must be set") + } + validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"}) + if !validator { + return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED") + } + if crq.Mode == "" { + return errors.New("validation-error: field Mode must be set") + } + validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"}) + if !validator { + return errors.New("validation-error: field Mode can be only EQ, NE or ANY") + } + if crq.Key == "" { + return errors.New("validation-error: field Key must be set") + } + if crq.Value == "" { + return errors.New("validation-error: field Value must be set") + } + + return nil +} + +// AffinityRuleAdd add affinity rule +func (c Compute) AffinityRuleAdd(ctx context.Context, req AffinityRuleAddRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/affinityRuleAdd" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/affinity_rule_remove.go b/pkg/cloudbroker/compute/affinity_rule_remove.go new file mode 100644 index 0000000..fd99db6 --- /dev/null +++ b/pkg/cloudbroker/compute/affinity_rule_remove.go @@ -0,0 +1,101 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" +) + +// Request struct for remove affinity rule +type AffinityRuleRemoveRequest struct { + // IDs of the compute instances + // Required: true + ComputeIDs []uint64 `url:"computeIds"` + + // Compute or node, for whom rule applies + // Required: true + Topology string `url:"topology"` + + // The degree of 'strictness' of this rule + // Should be one of: + // - RECOMMENDED + // - REQUIRED + // Required: true + Policy string `url:"policy"` + + // The comparison mode is 'value', recorded by the specified 'key' + // Should be one of: + // - EQ + // - EN + // - ANY + // Required: true + Mode string `url:"mode"` + + // Key that are taken into account when analyzing this rule will be identified + // Required: true + Key string `url:"key"` + + // Value that must match the key to be taken into account when analyzing this rule + // Required: true + Value string `url:"value"` +} + +func (crq AffinityRuleRemoveRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeIDs must be set") + } + if crq.Topology == "" { + return errors.New("validation-error: field Topology must be set") + } + validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"}) + if !validator { + return errors.New("validation-error: field Topology can be only compute or node") + } + if crq.Policy == "" { + return errors.New("validation-error: field Policy must be set") + } + validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"}) + if !validator { + return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED") + } + if crq.Mode == "" { + return errors.New("validation-error: field Mode must be set") + } + validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"}) + if !validator { + return errors.New("validation-error: field Mode can be only EQ, NE or ANY") + } + if crq.Key == "" { + return errors.New("validation-error: field Key must be set") + } + if crq.Value == "" { + return errors.New("validation-error: field Value must be set") + } + + return nil +} + +// AffinityRuleRemove remove affinity rule +func (c Compute) AffinityRuleRemove(ctx context.Context, req AffinityRuleRemoveRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/affinityRuleRemove" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/affinity_rules_clear.go b/pkg/cloudbroker/compute/affinity_rules_clear.go new file mode 100644 index 0000000..06d294a --- /dev/null +++ b/pkg/cloudbroker/compute/affinity_rules_clear.go @@ -0,0 +1,45 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for clear affinity rules +type AffinityRulesClearRequest struct { + // IDs of the compute instances + // Required: true + ComputeIDs []uint64 `url:"computeIds"` +} + +func (crq AffinityRulesClearRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeIDs must be set") + } + + return nil +} + +// AffinityRulesClear clear affinity rules +func (c Compute) AffinityRulesClear(ctx context.Context, req AffinityRulesClearRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/affinityRulesClear" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/anti_affinity_rule_add.go b/pkg/cloudbroker/compute/anti_affinity_rule_add.go new file mode 100644 index 0000000..fa1c98e --- /dev/null +++ b/pkg/cloudbroker/compute/anti_affinity_rule_add.go @@ -0,0 +1,101 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" +) + +// Request struct for add anti affinity rule +type AntiAffinityRuleAddRequest struct { + // IDs of the compute instances + // Required: true + ComputeIDs []uint64 `url:"computeIds"` + + // Compute or node, for whom rule applies + // Required: true + Topology string `url:"topology"` + + // The degree of 'strictness' of this rule + // Should be one of: + // - RECOMMENDED + // - REQUIRED + // Required: true + Policy string `url:"policy"` + + // The comparison mode is 'value', recorded by the specified 'key' + // Should be one of: + // - EQ + // - EN + // - ANY + // Required: true + Mode string `url:"mode"` + + // Key that are taken into account when analyzing this rule will be identified + // Required: true + Key string `url:"key"` + + // Value that must match the key to be taken into account when analyzing this rule + // Required: true + Value string `url:"value"` +} + +func (crq AntiAffinityRuleAddRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeIDs must be set") + } + if crq.Topology == "" { + return errors.New("validation-error: field Topology must be set") + } + validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"}) + if !validator { + return errors.New("validation-error: field Topology can be only compute or node") + } + if crq.Policy == "" { + return errors.New("validation-error: field Policy must be set") + } + validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"}) + if !validator { + return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED") + } + if crq.Mode == "" { + return errors.New("validation-error: field Mode must be set") + } + validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"}) + if !validator { + return errors.New("validation-error: field Mode can be only EQ, NE or ANY") + } + if crq.Key == "" { + return errors.New("validation-error: field Key must be set") + } + if crq.Value == "" { + return errors.New("validation-error: field Value must be set") + } + + return nil +} + +// AntiAffinityRuleAdd add anti affinity rule +func (c Compute) AntiAffinityRuleAdd(ctx context.Context, req AntiAffinityRuleAddRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/antiAffinityRuleAdd" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/anti_affinity_rule_clear.go b/pkg/cloudbroker/compute/anti_affinity_rule_clear.go new file mode 100644 index 0000000..5b3687f --- /dev/null +++ b/pkg/cloudbroker/compute/anti_affinity_rule_clear.go @@ -0,0 +1,45 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for clear anti affinity rules +type AntiAffinityRulesClearRequest struct { + // IDs of the compute instances + // Required: true + ComputeIDs []uint64 `url:"computeIds"` +} + +func (crq AntiAffinityRulesClearRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeIDs must be set") + } + + return nil +} + +// AntiAffinityRulesClear clear anti affinity rules +func (c Compute) AntiAffinityRulesClear(ctx context.Context, req AntiAffinityRulesClearRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/antiAffinityRulesClear" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/anti_affinity_rule_remove.go b/pkg/cloudbroker/compute/anti_affinity_rule_remove.go new file mode 100644 index 0000000..4bdc4ae --- /dev/null +++ b/pkg/cloudbroker/compute/anti_affinity_rule_remove.go @@ -0,0 +1,101 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" +) + +// Request struct for remove anti affinity rule +type AntiAffinityRuleRemoveRequest struct { + // IDs of the compute instances + // Required: true + ComputeIDs []uint64 `url:"computeIds"` + + // Compute or node, for whom rule applies + // Required: true + Topology string `url:"topology"` + + // The degree of 'strictness' of this rule + // Should be one of: + // - RECOMMENDED + // - REQUIRED + // Required: true + Policy string `url:"policy"` + + // The comparison mode is 'value', recorded by the specified 'key' + // Should be one of: + // - EQ + // - EN + // - ANY + // Required: true + Mode string `url:"mode"` + + // Key that are taken into account when analyzing this rule will be identified + // Required: true + Key string `url:"key"` + + // Value that must match the key to be taken into account when analyzing this rule + // Required: true + Value string `url:"value"` +} + +func (crq AntiAffinityRuleRemoveRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeIDs must be set") + } + if crq.Topology == "" { + return errors.New("validation-error: field Topology must be set") + } + validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"}) + if !validator { + return errors.New("validation-error: field Topology can be only compute or node") + } + if crq.Policy == "" { + return errors.New("validation-error: field Policy must be set") + } + validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"}) + if !validator { + return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED") + } + if crq.Mode == "" { + return errors.New("validation-error: field Mode must be set") + } + validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"}) + if !validator { + return errors.New("validation-error: field Mode can be only EQ, NE or ANY") + } + if crq.Key == "" { + return errors.New("validation-error: field Key must be set") + } + if crq.Value == "" { + return errors.New("validation-error: field Value must be set") + } + + return nil +} + +// AntiAffinityRuleRemove remove anti affinity rule +func (c Compute) AntiAffinityRuleRemove(ctx context.Context, req AntiAffinityRuleRemoveRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/antiAffinityRuleRemove" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/attach_gpu.go b/pkg/cloudbroker/compute/attach_gpu.go new file mode 100644 index 0000000..41e1110 --- /dev/null +++ b/pkg/cloudbroker/compute/attach_gpu.go @@ -0,0 +1,52 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for attach GPU for compute +type AttachGPURequest struct { + // Identifier compute + // Required: true + ComputeID uint64 `url:"computeId"` + + // Identifier vGPU + // Required: true + VGPUID uint64 `url:"vgpuId"` +} + +func (crq AttachGPURequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.VGPUID == 0 { + return errors.New("validation-error: field VGPUID must be set") + } + + return nil +} + +// AttachGPU attach GPU for compute, returns vGPU ID on success +func (c Compute) AttachGPU(ctx context.Context, req AttachGPURequest) (uint64, error) { + err := req.validate() + if err != nil { + return 0, err + } + + url := "/cloudbroker/compute/attachGpu" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/attach_pci_device.go b/pkg/cloudbroker/compute/attach_pci_device.go new file mode 100644 index 0000000..9fc931c --- /dev/null +++ b/pkg/cloudbroker/compute/attach_pci_device.go @@ -0,0 +1,52 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for atttach PCI device +type AttachPCIDeviceRequest struct { + // Identifier compute + // Required: true + ComputeID uint64 `url:"computeId"` + + // PCI device ID + // Required: true + DeviceID uint64 `url:"deviceId"` +} + +func (crq AttachPCIDeviceRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.DeviceID == 0 { + return errors.New("validation-error: field DeviceID must be set") + } + + return nil +} + +// AttachPCIDevice attach PCI device +func (c Compute) AttachPCIDevice(ctx context.Context, req AttachPCIDeviceRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/attachPciDevice" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/audits.go b/pkg/cloudbroker/compute/audits.go new file mode 100644 index 0000000..600cc61 --- /dev/null +++ b/pkg/cloudbroker/compute/audits.go @@ -0,0 +1,47 @@ +package compute + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get audit records +type AuditsRequest struct { + // ID of the compute + // Required: true + ComputeID uint64 `url:"computeId"` +} + +func (crq AuditsRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// Audits gets audit records for the specified compute object +func (c Compute) Audits(ctx context.Context, req AuditsRequest) (ListDetailedAudits, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/compute/audits" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListDetailedAudits{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/compute/boot_order_get.go b/pkg/cloudbroker/compute/boot_order_get.go new file mode 100644 index 0000000..af22cec --- /dev/null +++ b/pkg/cloudbroker/compute/boot_order_get.go @@ -0,0 +1,47 @@ +package compute + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get boot order +type BootOrderGetRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` +} + +func (crq BootOrderGetRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// BootOrderGet gets actual compute boot order information +func (c Compute) BootOrderGet(ctx context.Context, req BootOrderGetRequest) ([]string, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/compute/bootOrderGet" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + orders := make([]string, 0) + + err = json.Unmarshal(res, &orders) + if err != nil { + return nil, err + } + + return orders, nil +} diff --git a/pkg/cloudbroker/compute/boot_order_set.go b/pkg/cloudbroker/compute/boot_order_set.go new file mode 100644 index 0000000..9814c4a --- /dev/null +++ b/pkg/cloudbroker/compute/boot_order_set.go @@ -0,0 +1,65 @@ +package compute + +import ( + "context" + "encoding/json" + "errors" + "net/http" + + "github.com/rudecs/decort-sdk/internal/validators" +) + +// Request struct for set boot order +type BootOrderSetRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // List of boot devices + // Should be one of: + // - cdrom + // - network + // - hd + // Required: true + Order []string `url:"order"` +} + +func (crq BootOrderSetRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if len(crq.Order) == 0 { + return errors.New("validation-error: field Order must be set") + } + for _, value := range crq.Order { + if validate := validators.StringInSlice(value, []string{"cdrom", "network", "hd"}); !validate { + return errors.New("validation-error: field ImageType can be cdrom, network, hd") + } + } + + return nil +} + +// BootOrderSet sets compute boot order +func (c Compute) BootOrderSet(ctx context.Context, req BootOrderSetRequest) ([]string, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/compute/bootOrderSet" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + orders := make([]string, 0) + + err = json.Unmarshal(res, &orders) + if err != nil { + return nil, err + } + + return orders, nil +} diff --git a/pkg/cloudbroker/compute/cd_eject.go b/pkg/cloudbroker/compute/cd_eject.go new file mode 100644 index 0000000..6ff8937 --- /dev/null +++ b/pkg/cloudbroker/compute/cd_eject.go @@ -0,0 +1,49 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for eject CD image +type CDEjectRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Reason to eject + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq CDEjectRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must ve set") + } + + return nil +} + +// CDEject eject CD image to compute's CD-ROM +func (c Compute) CDEject(ctx context.Context, req CDEjectRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/cdEject" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, err +} diff --git a/pkg/cloudbroker/compute/cd_insert.go b/pkg/cloudbroker/compute/cd_insert.go new file mode 100644 index 0000000..d415d9a --- /dev/null +++ b/pkg/cloudbroker/compute/cd_insert.go @@ -0,0 +1,50 @@ +package compute + +import ( + "context" + "errors" + "net/http" +) + +// Request struct for insert new CD image +type CDInsertRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // ID of CD-ROM image + // Required: true + CDROMID uint64 `url:"cdromId"` + + // Reason to insert + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq CDInsertRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.CDROMID == 0 { + return errors.New("validation-error: field CDROMID must be set") + } + + return nil +} + +// CDInsert insert new CD image to compute's CD-ROM +func (c Compute) CDInsert(ctx context.Context, req CDInsertRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/cdInsert" + + _, err = c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + return true, nil +} diff --git a/pkg/cloudbroker/compute/clone.go b/pkg/cloudbroker/compute/clone.go new file mode 100644 index 0000000..3292fb0 --- /dev/null +++ b/pkg/cloudbroker/compute/clone.go @@ -0,0 +1,64 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for clone compute instance +type CloneRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Name of the clone + // Required: true + Name string `url:"name"` + + // Timestamp of the parent's snapshot to create clone from + // Required: false + SnapshotTimestamp uint64 `url:"snapshotTimestamp"` + + // Name of the parent's snapshot to create clone from + // Required: false + SnapshotName string `url:"snapshotName"` + + // Reason to clone + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq CloneRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.Name == "" { + return errors.New("validation-error: field Name must be set") + } + + return nil +} + +// Clone clones compute instance +func (c Compute) Clone(ctx context.Context, req CloneRequest) (uint64, error) { + err := req.validate() + if err != nil { + return 0, err + } + + url := "/cloudbroker/compute/clone" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/compute.go b/pkg/cloudbroker/compute/compute.go new file mode 100644 index 0000000..0f0e1c2 --- /dev/null +++ b/pkg/cloudbroker/compute/compute.go @@ -0,0 +1,16 @@ +// API Actor for managing Compute. This actor is a final API for admin to manage Compute +package compute + +import "github.com/rudecs/decort-sdk/interfaces" + +// Structure for creating request to compute +type Compute struct { + client interfaces.Caller +} + +// Builder for compute endpoints +func New(client interfaces.Caller) *Compute { + return &Compute{ + client: client, + } +} diff --git a/pkg/cloudbroker/compute/computeci_set.go b/pkg/cloudbroker/compute/computeci_set.go new file mode 100644 index 0000000..b345b09 --- /dev/null +++ b/pkg/cloudbroker/compute/computeci_set.go @@ -0,0 +1,52 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for set compute CI +type ComputeCISetRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // ID of the Compute CI + // Required: true + ComputeCIID uint64 `url:"computeciId"` +} + +func (crq ComputeCISetRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.ComputeCIID == 0 { + return errors.New("validation-error: field ComputeCIID must be set") + } + + return nil +} + +// ComputeCISet sets compute CI ID for compute +func (c Compute) ComputeCISet(ctx context.Context, req ComputeCISetRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/computeciSet" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/computeci_unset.go b/pkg/cloudbroker/compute/computeci_unset.go new file mode 100644 index 0000000..d86ee7f --- /dev/null +++ b/pkg/cloudbroker/compute/computeci_unset.go @@ -0,0 +1,45 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for unset compite CI +type ComputeCIUnsetRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` +} + +func (crq ComputeCIUnsetRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// ComputeCIUnset unsets compute CI ID from compute +func (c Compute) ComputeCIUnset(ctx context.Context, req ComputeCIUnsetRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/computeciUnset" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/create_template.go b/pkg/cloudbroker/compute/create_template.go new file mode 100644 index 0000000..3a9582a --- /dev/null +++ b/pkg/cloudbroker/compute/create_template.go @@ -0,0 +1,86 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" + "strings" +) + +// Request struct for create template +type CreateTemplateRequest struct { + // ID of the compute to create template from + // Required: true + ComputeID uint64 `url:"computeId"` + + // Name to assign to the template being created + // Required: true + Name string `url:"name"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` + + // Async API call + // For async call use CreateTemplateAsync + // For sync call use CreateTemplate + // Required: true + async bool `url:"async"` +} + +func (crq CreateTemplateRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.Name == "" { + return errors.New("validation-error: field Name must be set") + } + + return nil +} + +// CreateTemplateAsync create template from compute instance +func (c Compute) CreateTemplateAsync(ctx context.Context, req CreateTemplateRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + req.async = true + + url := "/cloudbroker/compute/createTemplate" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil +} + +// CreateTemplate create template from compute instance +func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest) (uint64, error) { + err := req.validate() + if err != nil { + return 0, err + } + + req.async = false + + url := "/cloudbroker/compute/createTemplate" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/delete.go b/pkg/cloudbroker/compute/delete.go new file mode 100644 index 0000000..6dd600e --- /dev/null +++ b/pkg/cloudbroker/compute/delete.go @@ -0,0 +1,57 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete compute +type DeleteRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Delete permanently + // Required: false + Permanently bool `url:"permanently,omitempty"` + + // Set True if you want to detach data disks (if any) from the compute before its deletion + // Required: false + DetachDisks bool `url:"detachDisks,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq DeleteRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field computeID must be set") + } + + return nil +} + +// Delete deletes compute +func (c Compute) Delete(ctx context.Context, req DeleteRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/delete" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/detach_gpu.go b/pkg/cloudbroker/compute/detach_gpu.go new file mode 100644 index 0000000..dacef72 --- /dev/null +++ b/pkg/cloudbroker/compute/detach_gpu.go @@ -0,0 +1,50 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for detach VGPU for compute +type DetachGPURequest struct { + // Identifier compute + // Required: true + ComputeID uint64 `url:"computeId"` + + // Identifier virtual GPU + // Required: false + VGPUID int64 `url:"vgpuId,omitempty"` +} + +func (crq DetachGPURequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// DetachGPU detach VGPU for compute. +// If param VGPU ID is equivalent -1, then detach all VGPU for compute +func (c Compute) DetachGPU(ctx context.Context, req DetachGPURequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/detachGpu" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/detach_pci_device.go b/pkg/cloudbroker/compute/detach_pci_device.go new file mode 100644 index 0000000..2fd0b94 --- /dev/null +++ b/pkg/cloudbroker/compute/detach_pci_device.go @@ -0,0 +1,52 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for detach PCI device +type DetachPCIDeviceRequest struct { + // Identifier compute + // Required: true + ComputeID uint64 `url:"computeId"` + + // PCI device ID + // Required: true + DeviceID uint64 `url:"deviceId"` +} + +func (crq DetachPCIDeviceRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.DeviceID == 0 { + return errors.New("validation-error: field DeviceID must be set") + } + + return nil +} + +// DetachPCIDevice detach PCI device +func (c Compute) DetachPciDevice(ctx context.Context, req DetachPCIDeviceRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/detachPciDevice" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/disable.go b/pkg/cloudbroker/compute/disable.go new file mode 100644 index 0000000..647cf4a --- /dev/null +++ b/pkg/cloudbroker/compute/disable.go @@ -0,0 +1,49 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for disable compute +type DisableRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq DisableRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field computeID must be set") + } + + return nil +} + +// Disable disables compute +func (c Compute) Disable(ctx context.Context, req DisableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/disable" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/disk_add.go b/pkg/cloudbroker/compute/disk_add.go new file mode 100644 index 0000000..e503759 --- /dev/null +++ b/pkg/cloudbroker/compute/disk_add.go @@ -0,0 +1,84 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for create and attach disk to compute +type DiskAddRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Name for disk + // Required: true + DiskName string `url:"diskName"` + + // Disk size in GB + // Required: true + Size uint64 `url:"size"` + + // Type of the disk + // Should be one of: + // - D + // - B + // Required: false + DiskType string `url:"diskType,omitempty"` + + // Storage endpoint provider ID + // By default the same with boot disk + // Required: false + SepID uint64 `url:"sepId,omitempty"` + + // Pool name + // By default will be chosen automatically + // Required: false + Pool string `url:"pool,omitempty"` + + // Optional description + // Required: false + Description string `url:"desc,omitempty"` + + // Specify image id for create disk from template + // Required: false + ImageID uint64 `url:"imageId,omitempty"` +} + +func (crq DiskAddRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.DiskName == "" { + return errors.New("validation-error: field DiskName must be set") + } + if crq.Size == 0 { + return errors.New("validation-error: field Size must be set") + } + + return nil +} + +// DiskAdd creates new disk and attach to compute +func (c Compute) DiskAdd(ctx context.Context, req DiskAddRequest) (uint64, error) { + err := req.validate() + if err != nil { + return 0, err + } + + url := "/cloudbroker/compute/diskAdd" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/disk_attach.go b/pkg/cloudbroker/compute/disk_attach.go new file mode 100644 index 0000000..07ad2d4 --- /dev/null +++ b/pkg/cloudbroker/compute/disk_attach.go @@ -0,0 +1,56 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for attach disk to compute +type DiskAttachRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // ID of the disk to attach + // Required: true + DiskID uint64 `url:"diskId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq DiskAttachRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.DiskID == 0 { + return errors.New("validation-error: field DiskID must be set") + } + + return nil +} + +// DiskAttach attach disk to compute +func (c Compute) DiskAttach(ctx context.Context, req DiskAttachRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/diskAttach" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/disk_del.go b/pkg/cloudbroker/compute/disk_del.go new file mode 100644 index 0000000..814e71c --- /dev/null +++ b/pkg/cloudbroker/compute/disk_del.go @@ -0,0 +1,60 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for detach and delete disk from compute +type DiskDelRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // ID of disk instance + // Required: true + DiskID uint64 `url:"diskId"` + + // False if disk is to be deleted to recycle bin + // Required: true + Permanently bool `url:"permanently"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq DiskDelRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.DiskID == 0 { + return errors.New("validation-error: field DiskID must be set") + } + + return nil +} + +// DiskDel delete disk and detach from compute +func (c Compute) DiskDel(ctx context.Context, req DiskDelRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/diskDel" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/disk_detach.go b/pkg/cloudbroker/compute/disk_detach.go new file mode 100644 index 0000000..d259a96 --- /dev/null +++ b/pkg/cloudbroker/compute/disk_detach.go @@ -0,0 +1,56 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for detach disk from compute +type DiskDetachRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // ID of the disk to detach + // Required: true + DiskID uint64 `url:"diskId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq DiskDetachRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.DiskID == 0 { + return errors.New("validation-error: field DiskID must be set") + } + + return nil +} + +// DiskDetach detach disk from compute +func (c Compute) DiskDetach(ctx context.Context, req DiskDetachRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/diskDetach" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/disk_qos.go b/pkg/cloudbroker/compute/disk_qos.go new file mode 100644 index 0000000..71ae002 --- /dev/null +++ b/pkg/cloudbroker/compute/disk_qos.go @@ -0,0 +1,59 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for change QOS of the disk +type DiskQOSRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // ID of the disk to apply limits + // Required: true + DiskID uint64 `url:"diskId"` + + // Limit IO for a certain disk total and read/write options are not allowed to be combined + // Required: true + Limits string `url:"limits"` +} + +func (crq DiskQOSRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.DiskID == 0 { + return errors.New("validation-error: field DiskID must be set") + } + if crq.Limits == "" { + return errors.New("validation-error: field Limits must be set") + } + + return nil +} + +// DiskQOS change QOS of the disk +func (c Compute) DiskQOS(ctx context.Context, req DiskQOSRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/diskQos" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/disk_resize.go b/pkg/cloudbroker/compute/disk_resize.go new file mode 100644 index 0000000..c58a9a1 --- /dev/null +++ b/pkg/cloudbroker/compute/disk_resize.go @@ -0,0 +1,63 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for change disk size +type DiskResizeRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // ID of the disk to resize + // Required: true + DiskID uint64 `url:"diskId"` + + // New disk size + // Required: true + Size uint64 `url:"size"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq DiskResizeRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.DiskID == 0 { + return errors.New("validation-error: field DiskID must be set") + } + if crq.Size == 0 { + return errors.New("validation-error: field Size must be set") + } + + return nil +} + +// DiskResize change disk size +func (c Compute) DiskResize(ctx context.Context, req DiskResizeRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/diskResize" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/enable.go b/pkg/cloudbroker/compute/enable.go new file mode 100644 index 0000000..b85e0e7 --- /dev/null +++ b/pkg/cloudbroker/compute/enable.go @@ -0,0 +1,49 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for enable compute +type EnableRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq EnableRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field computeID must be set") + } + + return nil +} + +// Enable enables compute +func (c Compute) Enable(ctx context.Context, req EnableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/enable" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/get.go b/pkg/cloudbroker/compute/get.go new file mode 100644 index 0000000..2da6f92 --- /dev/null +++ b/pkg/cloudbroker/compute/get.go @@ -0,0 +1,51 @@ +package compute + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request for get information about compute +type GetRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Reason to action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq GetRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// Get gets information about compute +func (c Compute) Get(ctx context.Context, req GetRequest) (*RecordCompute, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/compute/get" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + info := RecordCompute{} + + err = json.Unmarshal(res, &info) + if err != nil { + return nil, err + } + + return &info, nil +} diff --git a/pkg/cloudbroker/compute/get_audits.go b/pkg/cloudbroker/compute/get_audits.go new file mode 100644 index 0000000..7aa075b --- /dev/null +++ b/pkg/cloudbroker/compute/get_audits.go @@ -0,0 +1,51 @@ +package compute + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get compute audits +type GetAuditsRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Reason to action + // Required: true + Reason string `url:"reason,omitempty"` +} + +func (crq GetAuditsRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// GetAudits gets compute audits +func (c Compute) GetAudits(ctx context.Context, req GetAuditsRequest) (ListAudits, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/compute/getAudits" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListAudits{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/compute/get_console_url.go b/pkg/cloudbroker/compute/get_console_url.go new file mode 100644 index 0000000..38dd711 --- /dev/null +++ b/pkg/cloudbroker/compute/get_console_url.go @@ -0,0 +1,44 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strings" +) + +// Request struct for get console URL +type GetConsoleURLRequest struct { + // ID of compute instance to get console for + // Required: true + ComputeID uint64 `url:"computeId"` +} + +func (crq GetConsoleURLRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// GetConsoleURL gets computes console URL +func (c Compute) GetConsoleURL(ctx context.Context, req GetConsoleURLRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/compute/getConsoleUrl" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + result := strings.ReplaceAll(string(res), "\"", "") + + result = strings.ReplaceAll(result, "\\", "") + + return result, nil +} diff --git a/pkg/cloudbroker/compute/get_log.go b/pkg/cloudbroker/compute/get_log.go new file mode 100644 index 0000000..a1dbe58 --- /dev/null +++ b/pkg/cloudbroker/compute/get_log.go @@ -0,0 +1,46 @@ +package compute + +import ( + "context" + "errors" + "net/http" +) + +// Request struct for get compute logs +type GetLogRequest struct { + // ID of compute instance to get log for + // Required: true + ComputeID uint64 `url:"computeId"` + + // Path to log file + // Required: true + Path string `url:"path"` +} + +func (crq GetLogRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.Path == "" { + return errors.New("validation-error: field Path must be set") + } + + return nil +} + +// GetLog gets compute's log file by path +func (c Compute) GetLog(ctx context.Context, req GetLogRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/compute/getLog" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + return string(res), nil +} diff --git a/pkg/cloudbroker/compute/list.go b/pkg/cloudbroker/compute/list.go new file mode 100644 index 0000000..1614e2a --- /dev/null +++ b/pkg/cloudbroker/compute/list.go @@ -0,0 +1,42 @@ +package compute + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get list available computes +type ListRequest struct { + // Include deleted computes + // Required: false + IncludeDeleted bool `url:"includedeleted,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} + +// List gets list of the available computes. +// Filtering based on status is possible +func (c Compute) List(ctx context.Context, req ListRequest) (ListComputes, error) { + url := "/cloudbroker/compute/list" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListComputes{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/compute/list_deleted.go b/pkg/cloudbroker/compute/list_deleted.go new file mode 100644 index 0000000..07b6ecc --- /dev/null +++ b/pkg/cloudbroker/compute/list_deleted.go @@ -0,0 +1,37 @@ +package compute + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get deleted computes list +type ListDeletedRequest struct { + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} + +// ListDeleted gets list all deleted computes +func (c Compute) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListComputes, error) { + url := "/cloudbroker/compute/listDeleted" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListComputes{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/compute/list_gpu.go b/pkg/cloudbroker/compute/list_gpu.go new file mode 100644 index 0000000..38be234 --- /dev/null +++ b/pkg/cloudbroker/compute/list_gpu.go @@ -0,0 +1,51 @@ +package compute + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get list GPU for compute +type ListGPURequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Also list destroyed + // Required: false + ListDestroyed bool `url:"list_destroyed,omitempty"` +} + +func (crq ListGPURequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// ListVGPU gets list GPU for compute +func (c Compute) ListVGPU(ctx context.Context, req ListGPURequest) ([]interface{}, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/compute/listGpu" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := make([]interface{}, 0) + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/compute/list_pci_device.go b/pkg/cloudbroker/compute/list_pci_device.go new file mode 100644 index 0000000..7d5f37f --- /dev/null +++ b/pkg/cloudbroker/compute/list_pci_device.go @@ -0,0 +1,47 @@ +package compute + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get list PCI devices +type ListPCIDeviceRequest struct { + // Identifier compute + // Required: true + ComputeID uint64 `url:"computeId"` +} + +func (crq ListPCIDeviceRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// ListPCIDevice gets list PCI device +func (c Compute) ListPCIDevice(ctx context.Context, req ListPCIDeviceRequest) (ListPCIDevices, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/compute/listPciDevice" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListPCIDevices{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/compute/mass_delete.go b/pkg/cloudbroker/compute/mass_delete.go new file mode 100644 index 0000000..4f357de --- /dev/null +++ b/pkg/cloudbroker/compute/mass_delete.go @@ -0,0 +1,53 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete several computes +type MassDeleteRequest struct { + // IDs of compute instances to delete + // Required: true + ComputeIDs []uint64 `url:"computeIds"` + + // Delete computes permanently + // Required: false + Permanently bool `url:"permanently,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq MassDeleteRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeIDs must be set") + } + + return nil +} + +// MassDelete starts jobs to delete several computes +func (c Compute) MassDelete(ctx context.Context, req MassDeleteRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/massDelete" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/mass_reboot.go b/pkg/cloudbroker/compute/mass_reboot.go new file mode 100644 index 0000000..f32dd2e --- /dev/null +++ b/pkg/cloudbroker/compute/mass_reboot.go @@ -0,0 +1,49 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for reboot several computes +type MassRebootRequest struct { + // IDs of compute instances to reboot + // Required: true + ComputeIDs []uint64 `url:"computeIds"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq MassRebootRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeIDs must be set") + } + + return nil +} + +// MassReboot starts jobs to reboot several computes +func (c Compute) MassReboot(ctx context.Context, req MassRebootRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/massReboot" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/mass_repair_boot_fs.go b/pkg/cloudbroker/compute/mass_repair_boot_fs.go new file mode 100644 index 0000000..d50993a --- /dev/null +++ b/pkg/cloudbroker/compute/mass_repair_boot_fs.go @@ -0,0 +1,49 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for repair boot disk filesystem on several computes +type MassRepairBootFSRequest struct { + // IDs of compute instances which boot file systems will be repaired + // Required: true + ComputeIDs []uint64 `url:"computeIds"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq MassRepairBootFSRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeIDs must be set") + } + + return nil +} + +// MassRepairBootFS repair boot disk filesystem on several computes +func (c Compute) MassRepairBootFS(ctx context.Context, req MassRepairBootFSRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/massRepairBootFs" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/mass_start.go b/pkg/cloudbroker/compute/mass_start.go new file mode 100644 index 0000000..03b1c61 --- /dev/null +++ b/pkg/cloudbroker/compute/mass_start.go @@ -0,0 +1,49 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for start several computes +type MassStartRequest struct { + // IDs of compute instances to start + // Required: true + ComputeIDs []uint64 `url:"computeIds"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq MassStartRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeIDs must be set") + } + + return nil +} + +// MassStart starts jobs to start several computes +func (c Compute) MassStart(ctx context.Context, req MassStartRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/massStart" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/mass_stop.go b/pkg/cloudbroker/compute/mass_stop.go new file mode 100644 index 0000000..b3695f2 --- /dev/null +++ b/pkg/cloudbroker/compute/mass_stop.go @@ -0,0 +1,53 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for several stop computes +type MassStopRequest struct { + // IDs of compute instances to stop + // Required: true + ComputeIDs []uint64 `url:"computeIds"` + + // Force stop compute + // Required: false + Force bool `url:"force,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq MassStopRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeIDs must be set") + } + + return nil +} + +// MassStop starts jobs to stop several computes +func (c Compute) MassStop(ctx context.Context, req MassStopRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/massStop" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/migrate.go b/pkg/cloudbroker/compute/migrate.go new file mode 100644 index 0000000..9ae6fc3 --- /dev/null +++ b/pkg/cloudbroker/compute/migrate.go @@ -0,0 +1,58 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for migrate compute +type MigrateRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Particular Stack ID to migrate this compute to + // Required: false + TargetStackID uint64 `url:"targetStackId,omitempty"` + + // If live migration fails, destroy compute + // on source node and recreate on the target + // Required: false + Force bool `url:"force,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq MigrateRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// Migrate migrates compute to another stack +func (c Compute) Migrate(ctx context.Context, req MigrateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/migrate" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/migrate_storage.go b/pkg/cloudbroker/compute/migrate_storage.go new file mode 100644 index 0000000..7ad25e9 --- /dev/null +++ b/pkg/cloudbroker/compute/migrate_storage.go @@ -0,0 +1,70 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strings" +) + +// Request struct for migration +type MigrateStorageRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // SEP ID to migrate disks + // Required: true + SEPID uint64 `url:"sepId"` + + // SEP pool name to migrate disks + // Required: true + PoolName string `url:"poolName"` + + // Target stack ID + // Required: true + StackID uint64 `url:"stackId"` + + // Async API call + // Required: true + Sync bool `url:"sync"` +} + +func (crq MigrateStorageRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + if crq.PoolName == "" { + return errors.New("validation-error: field PoolName must be set") + } + if crq.StackID == 0 { + return errors.New("validation-error: field StackID must be set") + } + + return nil +} + +// MigrateStorage gets complex compute migration +// Compute will be migrated to specified stack, and compute disks will +// be migrated to specified SEP to specified pool. +// This action can take up to 84 hours +func (c Compute) MigrateStorage(ctx context.Context, req MigrateStorageRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/compute/migrateStorage" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil +} diff --git a/pkg/cloudbroker/compute/migrate_storage_abort.go b/pkg/cloudbroker/compute/migrate_storage_abort.go new file mode 100644 index 0000000..d586d08 --- /dev/null +++ b/pkg/cloudbroker/compute/migrate_storage_abort.go @@ -0,0 +1,42 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strings" +) + +// Request struct for abort migration +type MigrateStorageAbortRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` +} + +func (crq MigrateStorageAbortRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// MigrateStorageAbort abort complex compute migration job +func (c Compute) MigrateStorageAbort(ctx context.Context, req MigrateStorageAbortRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/compute/migrateStorageAbort" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil +} diff --git a/pkg/cloudbroker/compute/migrate_storage_clean_up.go b/pkg/cloudbroker/compute/migrate_storage_clean_up.go new file mode 100644 index 0000000..66dbdac --- /dev/null +++ b/pkg/cloudbroker/compute/migrate_storage_clean_up.go @@ -0,0 +1,44 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strings" +) + +// Request struct for cleanup resources after finished migration +type MigrateStorageCleanUpRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` +} + +func (crq MigrateStorageCleanUpRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// MigrateStorageCleanUp cleanup resources after finished (success of failed) complex compute migration. +// If the migration was successful, then old disks will be removed, else new (target) disks will be removed. +// Do it wisely! +func (c Compute) MigrateStorageCleanUp(ctx context.Context, req MigrateStorageCleanUpRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/compute/migrateStorageCleanup" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil +} diff --git a/pkg/cloudbroker/compute/migrate_storage_info.go b/pkg/cloudbroker/compute/migrate_storage_info.go new file mode 100644 index 0000000..981e434 --- /dev/null +++ b/pkg/cloudbroker/compute/migrate_storage_info.go @@ -0,0 +1,42 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strings" +) + +// Request struct for get info about migration +type MigrateStorageInfoRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` +} + +func (crq MigrateStorageInfoRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// MigrateStorageInfo gets info about last (include ongoing) storage migration +func (c Compute) MigrateStorageInfo(ctx context.Context, req MigrateStorageInfoRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/compute/migrateStorageInfo" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil +} diff --git a/pkg/cloudbroker/compute/models.go b/pkg/cloudbroker/compute/models.go new file mode 100644 index 0000000..f83ff63 --- /dev/null +++ b/pkg/cloudbroker/compute/models.go @@ -0,0 +1,778 @@ +package compute + +// Access Control List +type RecordACL struct { + // Account ACL list + AccountACL ListACL `json:"accountACL"` + + // Compute ACL list + ComputeACL []ItemComputeACL `json:"computeACL"` + + // Resource group ACL list + RGACL ListACL `json:"rgACL"` +} + +// ACL information +type ItemACL struct { + // Explicit + Explicit bool `json:"explicit"` + + // GUID + GUID string `json:"guid"` + + // Right + Right string `json:"right"` + + // Status + Status string `json:"status"` + + // Type + Type string `json:"type"` + + // User group ID + UserGroupID string `json:"userGroupId"` +} + +// ACL compute information +type ItemComputeACL struct { + // Explicit + Explicit string `json:"explicit"` + + // GUID + GUID string `json:"guid"` + + // Right + Right string `json:"right"` + + // Status + Status string `json:"status"` + + // Type + Type string `json:"type"` + + // User group ID + UserGroupID string `json:"userGroupId"` +} + +// List ACL +type ListACL []ItemACL + +// Main information about snapshot +type ItemSnapshot struct { + // List of disk IDs + Disks []uint64 `json:"disks"` + + // GUID + GUID string `json:"guid"` + + // Label + Label string `json:"label"` + + // Timestamp + Timestamp uint64 `json:"timestamp"` +} + +// List of snapshots +type ListSnapshots []ItemSnapshot + +// Main information about snapshot usage +type ItemSnapshotUsage struct { + // Count + Count uint64 `json:"count,omitempty"` + + // Stored + Stored float64 `json:"stored"` + + // Label + Label string `json:"label,omitempty"` + + // Timestamp + Timestamp uint64 `json:"timestamp,omitempty"` +} + +// List of snapshot usage +type ListSnapshotUsage []ItemSnapshotUsage + +// QOS +type QOS struct { + // ERate + ERate uint64 `json:"eRate"` + + // GUID + GUID string `json:"guid"` + + // InBurst + InBurst uint64 `json:"inBurst"` + + // InRate + InRate uint64 `json:"inRate"` +} + +// Main information about attached network +type RecordNetAttach struct { + // Connection ID + ConnID uint64 `json:"connId"` + + // Connection type + ConnType string `json:"connType"` + + // Default GW + DefGW string `json:"defGw"` + + // FLIPGroup ID + FLIPGroupID uint64 `json:"flipgroupId"` + + // GUID + GUID string `json:"guid"` + + // IP address + IPAddress string `json:"ipAddress"` + + // Listen SSH + ListenSSH bool `json:"listenSsh"` + + // MAC + MAC string `json:"mac"` + + // Name + Name string `json:"name"` + + // Network ID + NetID uint64 `json:"netId"` + + // Network mask + NetMask uint64 `json:"netMask"` + + // Network type + NetType string `json:"netType"` + + // PCI slot + PCISlot uint64 `json:"pciSlot"` + + // QOS + QOS QOS `json:"qos"` + + // Target + Target string `json:"target"` + + // Type + Type string `json:"type"` + + // List VNF IDs + VNFs []uint64 `json:"vnfs"` +} + +// Main information about affinity relations +type RecordAffinityRelations struct { + // Other node + OtherNode []interface{} `json:"otherNode"` + + // Other node indirect + OtherNodeIndirect []interface{} `json:"otherNodeIndirect"` + + // Other node indirect soft + OtherNodeIndirectSoft []interface{} `json:"otherNodeIndirectSoft"` + + // Other node soft + OtherNodeSoft []interface{} `json:"otherNodeSoft"` + + // Same node + SameNode []interface{} `json:"sameNode"` + + // Same node soft + SameNodeSoft []interface{} `json:"sameNodeSoft"` +} + +// Detailed information about audit +type ItemDetailedAudit struct { + // Call + Call string `json:"call"` + + // Response time + ResponseTime float64 `json:"responsetime"` + + // Status code + StatusCode uint64 `json:"statuscode"` + + // Timestamp + Timestamp float64 `json:"timestamp"` + + // User + User string `json:"user"` +} + +// List of detailed audit +type ListDetailedAudits []ItemDetailedAudit + +// Main information about port forward +type ItemPFW struct { + // ID + ID uint64 `json:"id"` + + // Local IP + LocalIP string `json:"localIp"` + + // Local port + LocalPort uint64 `json:"localPort"` + + // Protocol + Protocol string `json:"protocol"` + + // Public port end + PublicPortEnd uint64 `json:"publicPortEnd"` + + // Public port start + PublicPortStart uint64 `json:"publicPortStart"` + + // Virtuel machine ID + VMID uint64 `json:"vmId"` +} + +// List port forwards +type ListPFW []ItemPFW + +// Main information about rule +type ItemRule struct { + // GUID + GUID string `json:"guid"` + + // Key + Key string `json:"key"` + + // Mode + Mode string `json:"mode"` + + // Policy + Policy string `json:"policy"` + + // Topology + Topology string `json:"topology"` + + // Value + Value string `json:"value"` +} + +// List rules +type ListRules []ItemRule + +// Main information about IO tune +type IOTune struct { + // ReadBytesSec + ReadBytesSec uint64 `json:"read_bytes_sec"` + + // ReadBytesSecMax + ReadBytesSecMax uint64 `json:"read_bytes_sec_max"` + + // ReadIOPSSec + ReadIOPSSec uint64 `json:"read_iops_sec"` + + // ReadIOPSSecMax + ReadIOPSSecMax uint64 `json:"read_iops_sec_max"` + + // SizeIOPSSec + SizeIOPSSec uint64 `json:"size_iops_sec"` + + // TotalBytesSec + TotalBytesSec uint64 `json:"total_bytes_sec"` + + // TotalBytesSecMax + TotalBytesSecMax uint64 `json:"total_bytes_sec_max"` + + // TotalIOPSSec + TotalIOPSSec uint64 `json:"total_iops_sec"` + + // TotalIOPSSecMax + TotalIOPSSecMax uint64 `json:"total_iops_sec_max"` + + // WriteBytesSec + WriteBytesSec uint64 `json:"write_bytes_sec"` + + // WriteBytesSecMax + WriteBytesSecMax uint64 `json:"write_bytes_sec_max"` + + // WriteIOPSSec + WriteIOPSSec uint64 `json:"write_iops_sec"` + + // WriteIOPSSecMax + WriteIOPSSecMax uint64 `json:"write_iops_sec_max"` +} + +// Detailed information about snapshot +type ItemSnapshotDetailed struct { + // GUID + GUID string `json:"guid"` + + // Label + Label string `json:"label"` + + // Resource ID + ResID string `json:"resId"` + + // SnapSetGUID + SnapSetGUID string `json:"snapSetGuid"` + + // SnapSetTime + SnapSetTime uint64 `json:"snapSetTime"` + + // TimeStamp + TimeStamp uint64 `json:"timestamp"` +} + +// List detailed snapshots +type ListDetailedSnapshots []ItemSnapshotDetailed + +// Main information about disk +type ItemDisk struct { + // CKey + CKey string `json:"_ckey"` + + // Meta + Meta []interface{} `json:"_meta"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Access Control List + ACL ItemACL `json:"acl"` + + // Boot partition + BootPartition uint64 `json:"bootPartition"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // Destruction time + DestructionTime uint64 `json:"destructionTime"` + + // Disk path + DiskPath string `json:"diskPath"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Image ID + ImageID uint64 `json:"imageId"` + + // List image IDs + Images []uint64 `json:"images"` + + // IOTune + IOTune IOTune `json:"iotune"` + + // IQN + IQN string `json:"iqn"` + + // Login + Login string `json:"login"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Order + Order uint64 `json:"order"` + + // Params + Params string `json:"params"` + + // Parent ID + ParentID uint64 `json:"parentId"` + + // Password + Password string `json:"passwd"` + + // PCI slot + PCISlot uint64 `json:"pciSlot"` + + // Pool + Pool string `json:"pool"` + + // Purge attempts + PurgeAttempts uint64 `json:"purgeAttempts"` + + // Purge time + PurgeTime uint64 `json:"purgeTime"` + + // Reality device number + RealityDeviceNumber uint64 `json:"realityDeviceNumber"` + + // Reference ID + ReferenceID string `json:"referenceId"` + + // Resource ID + ResID string `json:"resId"` + + // Resource name + ResName string `json:"resName"` + + // Role + Role string `json:"role"` + + // SEP ID + SEPID uint64 `json:"sepId"` + + // Size max + SizeMax uint64 `json:"sizeMax"` + + // Size used + SizeUsed uint64 `json:"sizeUsed"` + + // List detailed snapshots + Snapshots ListDetailedSnapshots `json:"snapshots"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Type + Type string `json:"type"` + + // Updated by + UpdatedBy uint64 `json:"updatedBy,omitempty"` + + // Virtual machine ID + VMID uint64 `json:"vmid"` +} + +// List disks +type ListDisks []ItemDisk + +// Main information about interface +type ItemInterface struct { + // Connection ID + ConnID uint64 `json:"connId"` + + // Connection type + ConnType string `json:"connType"` + + // Default GW + DefGW string `json:"defGw"` + + // FLIPGroup ID + FLIPGroupID uint64 `json:"flipgroupId"` + + // GUID + GUID string `json:"guid"` + + // IP address + IPAddress string `json:"ipAddress"` + + // Listen SSH or not + ListenSSH bool `json:"listenSsh"` + + // MAC + MAC string `json:"mac"` + + // Name + Name string `json:"name"` + + // Network ID + NetID uint64 `json:"netId"` + + // Network mask + NetMask uint64 `json:"netMask"` + + // Network type + NetType string `json:"netType"` + + // PCI slot + PCISlot uint64 `json:"pciSlot"` + + // QOS + QOS QOS `json:"qos"` + + // Target + Target string `json:"target"` + + // Type + Type string `json:"type"` + + // List VNF IDs + VNFs []uint64 `json:"vnfs"` +} + +// List interfaces +type ListInterfaces []ItemInterface + +// Main information about OS user +type ItemOSUser struct { + // GUID + GUID string `json:"guid"` + + // Login + Login string `json:"login"` + + // Password + Password string `json:"password"` + + // Public key + PubKey string `json:"pubkey"` +} + +// List OS users +type ListOSUsers []ItemOSUser + +// Information about compute +type InfoCompute struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Access Control List + ACL []interface{} `json:"acl"` + + // Affinity label + AffinityLabel string `json:"affinityLabel"` + + // Affinity rules + AffinityRules ListRules `json:"affinityRules"` + + // Affinity weight + AffinityWeight uint64 `json:"affinityWeight"` + + // Anti affinity rules + AntiAffinityRules ListRules `json:"antiAffinityRules"` + + // Architecture + Arch string `json:"arch"` + + // Boot order + BootOrder []string `json:"bootOrder"` + + // Boot disk size + BootDiskSize uint64 `json:"bootdiskSize"` + + // Clone reference + CloneReference uint64 `json:"cloneReference"` + + // List clone IDs + Clones []uint64 `json:"clones"` + + // Compute CI ID + ComputeCIID uint64 `json:"computeciId"` + + // Number of CPU + CPUs uint64 `json:"cpus"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Custom fields + CustomFields map[string]interface{} `json:"customFields"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // Devices + Devices interface{} `json:"devices"` + + // Driver + Driver string `json:"driver"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Image ID + ImageID uint64 `json:"imageId"` + + // List interfaces + Interfaces ListInterfaces `json:"interfaces"` + + // Lock status + LockStatus string `json:"lockStatus"` + + // Manager ID + ManagerID uint64 `json:"managerId"` + + // Manager type + ManagerType string `json:"managerType"` + + // Migration job + MigrationJob uint64 `json:"migrationjob"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // List OS users + OSUsers ListOSUsers `json:"osUsers"` + + // Pinned + Pinned bool `json:"pinned"` + + // Number of RAM + RAM uint64 `json:"ram"` + + // Reference ID + ReferenceID string `json:"referenceId"` + + // Registered + Registered bool `json:"registered"` + + // Resource name + ResName string `json:"resName"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // SnapSets + SnapSets ListSnapshots `json:"snapSets"` + + // Stack ID + StackID uint64 `json:"stackId"` + + // Stack name + StackName string `json:"stackName"` + + // Stateless SEP ID + StatelessSEPID uint64 `json:"statelessSepId"` + + // Stateless SEP Type + StatelessSEPType string `json:"statelessSepType"` + + // Status + Status string `json:"status"` + + // Tags + Tags map[string]interface{} `json:"tags"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // User managed + UserManaged bool `json:"userManaged"` + + // Userdata + Userdata interface{} `json:"userdata"` + + // List VGPU IDs + VGPUs []uint64 `json:"vgpus"` + + // Virtual image ID + VirtualImageID uint64 `json:"virtualImageId"` +} + +// Detailed information about compute +type RecordCompute struct { + // List disks + Disks ListDisks `json:"disks"` + + // Main information about compute + InfoCompute +} + +// Main information about compute for list +type ItemCompute struct { + // List of disk IDs + Disks []uint64 `json:"disks"` + + // Main information about compute + InfoCompute + + // Total disk size + TotalDiskSize uint64 `json:"totalDiskSize"` + + // VINS connected + VINSConnected uint64 `json:"vinsConnected"` +} + +// List computes +type ListComputes []ItemCompute + +// Short information about audir +type ItemAudit struct { + // Epoch + Epoch float64 `json:"epoch"` + + // Message + Message string `json:"message"` +} + +// List audits +type ListAudits []ItemAudit + +// Main information about PCI device +type ItemPCIDevice struct { + // CKey + CKey string `json:"_ckey"` + + // Meta + Meta []interface{} `json:"_meta"` + + // Compute ID + ComputeID uint64 `json:"computeId"` + + // Description + Description string `json:"description"` + + // GUID + GUID uint64 `json:"guid"` + + // HwPath + HwPath string `json:"hwPath"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Stack ID + StackID uint64 `json:"stackId"` + + // Status + Status string `json:"status"` + + // System name + SystemName string `json:"systemName"` +} + +// List PCI devices +type ListPCIDevices []ItemPCIDevice diff --git a/pkg/cloudbroker/compute/move_to_rg.go b/pkg/cloudbroker/compute/move_to_rg.go new file mode 100644 index 0000000..7bcd861 --- /dev/null +++ b/pkg/cloudbroker/compute/move_to_rg.go @@ -0,0 +1,67 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for move compute new resource group +type MoveToRGRequest struct { + // ID of the compute instance to move + // Required: true + ComputeID uint64 `url:"computeId"` + + // ID of the target resource group + // Required: true + RGID uint64 `url:"rgId"` + + // New name for the compute upon successful move, + // if name change required. + // Pass empty string if no name change necessary + // Required: false + Name string `url:"name,omitempty"` + + // Should the compute be restarted upon successful move + // Required: false + Autostart bool `url:"autostart,omitempty"` + + // By default moving compute in a running state is not allowed. + // Set this flag to True to force stop running compute instance prior to move. + // Required: false + ForceStop bool `url:"forceStop,omitempty"` +} + +func (crq MoveToRGRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.RGID == 0 { + return errors.New("validation-error: field RGID must be set") + } + + return nil +} + +// MoveToRG moves compute instance to new resource group +func (c Compute) Validate(ctx context.Context, req MoveToRGRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/moveToRg" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/net_attach.go b/pkg/cloudbroker/compute/net_attach.go new file mode 100644 index 0000000..5acaafc --- /dev/null +++ b/pkg/cloudbroker/compute/net_attach.go @@ -0,0 +1,79 @@ +package compute + +import ( + "context" + "encoding/json" + "errors" + "net/http" + + "github.com/rudecs/decort-sdk/internal/validators" +) + +// Request struct for attach network +type NetAttachRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Network type + // 'EXTNET' for connect to external network directly + // and 'VINS' for connect to ViNS + // Required: true + NetType string `url:"netType"` + + // Network ID for connect to + // For EXTNET - external network ID + // For VINS - VINS ID + // Required: true + NetID uint64 `url:"netId"` + + // Directly required IP address for new network interface + // Required: true + IPAddr string `url:"ipAddr,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq NetAttachRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.NetType == "" { + return errors.New("validation-error: field NetType must be set") + } + validator := validators.StringInSlice(crq.NetType, []string{"EXTNET", "VINS"}) + if !validator { + return errors.New("validation-error: field NetType can be only EXTNET or VINS") + } + if crq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// NetAttach attach network to compute and gets info about network +func (c Compute) NetAttach(ctx context.Context, req NetAttachRequest) (*RecordNetAttach, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/compute/netAttach" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + info := RecordNetAttach{} + + err = json.Unmarshal(res, &info) + if err != nil { + return nil, err + } + + return &info, nil +} diff --git a/pkg/cloudbroker/compute/net_detach.go b/pkg/cloudbroker/compute/net_detach.go new file mode 100644 index 0000000..0816732 --- /dev/null +++ b/pkg/cloudbroker/compute/net_detach.go @@ -0,0 +1,57 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for detach networ to compute +type NetDetachRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // IP of the network interface + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // MAC of the network interface + // Required: false + MAC string `url:"mac,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq NetDetachRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// NetDetach detach network to compute +func (c Compute) NetDetach(ctx context.Context, req NetDetachRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/netDetach" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/net_qos.go b/pkg/cloudbroker/compute/net_qos.go new file mode 100644 index 0000000..519afec --- /dev/null +++ b/pkg/cloudbroker/compute/net_qos.go @@ -0,0 +1,80 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" +) + +// Request struct for update QOS +type NetQOSRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Network ID + // Required: true + NetID uint64 `url:"netId"` + + // Network type + // Should be one of: + // - VINS + // - EXTNET + // Required: true + NetType string `url:"netType"` + + // Internal traffic, kbit + // Required: false + IngressRate uint64 `url:"ingress_rate,omitempty"` + + // Internal traffic burst, kbit + // Required: false + IngressBurst uint64 `url:"ingress_burst,omitempty"` + + // External traffic rate, kbit + // Required: false + EgressRate uint64 `url:"egress_rate,omitempty"` +} + +func (crq NetQOSRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.NetType == "" { + return errors.New("validation-error: field NetType must be set") + } + validator := validators.StringInSlice(crq.NetType, []string{"EXTNET", "VINS"}) + if !validator { + return errors.New("validation-error: field NetType can be only EXTNET or VINS") + } + if crq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// NetQOS update compute interfaces QOS +func (c Compute) NetQOS(ctx context.Context, req NetQOSRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/netQos" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/pause.go b/pkg/cloudbroker/compute/pause.go new file mode 100644 index 0000000..b109890 --- /dev/null +++ b/pkg/cloudbroker/compute/pause.go @@ -0,0 +1,49 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for pause compute +type PauseRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq PauseRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// Pause pause compute +func (c Compute) Pause(ctx context.Context, req PauseRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/pause" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/pfw_add.go b/pkg/cloudbroker/compute/pfw_add.go new file mode 100644 index 0000000..56df46a --- /dev/null +++ b/pkg/cloudbroker/compute/pfw_add.go @@ -0,0 +1,83 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" +) + +// Request struct for add port forward rule +type PFWAddRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // External start port number for the rule + // Required: true + PublicPortStart uint64 `url:"publicPortStart"` + + // End port number (inclusive) for the ranged rule + // Required: false + PublicPortEnd uint64 `url:"publicPortEnd,omitempty"` + + // Internal base port number + // Required: true + LocalBasePort uint64 `url:"localBasePort"` + + // Network protocol + // Should be one of: + // - tcp + // - udp + // Required: true + Proto string `url:"proto"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq PFWAddRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.PublicPortStart == 0 { + return errors.New("validation-error: field PublicPortStart must be set") + } + if crq.LocalBasePort == 0 { + return errors.New("validation-error: field LocalBasePort must be set") + } + if crq.Proto == "" { + return errors.New("validation-error: field Proto must be set") + } + validate := validators.StringInSlice(crq.Proto, []string{"tcp", "udp"}) + if !validate { + return errors.New("validation-error: field Proto must be tcp or udp") + } + + return nil +} + +// PFWAdd add port forward rule +func (c Compute) PFWAdd(ctx context.Context, req PFWAddRequest) (uint64, error) { + err := req.validate() + if err != nil { + return 0, err + } + + url := "/cloudbroker/compute/pfwAdd" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/pfw_del.go b/pkg/cloudbroker/compute/pfw_del.go new file mode 100644 index 0000000..9f3cee7 --- /dev/null +++ b/pkg/cloudbroker/compute/pfw_del.go @@ -0,0 +1,72 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete port forward rule +type PFWDelRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // ID of the rule to delete. If specified, all other arguments will be ignored + // Required: false + RuleID uint64 `url:"ruleId,omitempty"` + + // External start port number for the rule + // Required: false + PublicPortStart uint64 `url:"publicPortStart,omitempty"` + + // End port number (inclusive) for the ranged rule + // Required: false + PublicPortEnd uint64 `url:"publicPortEnd,omitempty"` + + // Internal base port number + // Required: false + LocalBasePort uint64 `url:"localBasePort,omitempty"` + + // Network protocol + // Should be one of: + // - tcp + // - udp + // Required: false + Proto string `url:"proto,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq PFWDelRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// PFWDel delete port forward rule +func (c Compute) PFWDel(ctx context.Context, req PFWDelRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/pfwDel" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/pfw_list.go b/pkg/cloudbroker/compute/pfw_list.go new file mode 100644 index 0000000..d3a6c00 --- /dev/null +++ b/pkg/cloudbroker/compute/pfw_list.go @@ -0,0 +1,51 @@ +package compute + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get list port forwards +type PFWListRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq PFWListRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// PFWList gets compute port forwards list +func (c Compute) PFWList(ctx context.Context, req PFWListRequest) (ListPFW, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/compute/pfwList" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListPFW{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/compute/pin_to_stack.go b/pkg/cloudbroker/compute/pin_to_stack.go new file mode 100644 index 0000000..68ebef1 --- /dev/null +++ b/pkg/cloudbroker/compute/pin_to_stack.go @@ -0,0 +1,56 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for pin comptute to stack +type PinToStackRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Stack ID to pin to + // Required: true + TargetStackID uint64 `url:"targetStackId"` + + // Try to migrate or not if compute in running states + // Required: false + Force bool `url:"force"` +} + +func (crq PinToStackRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.TargetStackID == 0 { + return errors.New("validation-error: field TargetStackID must be set") + } + + return nil +} + +// PinToStack pin compute to current stack +func (c Compute) PinToStack(ctx context.Context, req PinToStackRequest) (uint64, error) { + err := req.validate() + if err != nil { + return 0, err + } + + url := "/cloudbroker/compute/pinToStack" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/power_cycle.go b/pkg/cloudbroker/compute/power_cycle.go new file mode 100644 index 0000000..c0b33a0 --- /dev/null +++ b/pkg/cloudbroker/compute/power_cycle.go @@ -0,0 +1,45 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for force stop and start compute +type PowerCycleRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` +} + +func (crq PowerCycleRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// PowerCycle makes force stop and start compute +func (c Compute) PowerCycle(ctx context.Context, req PowerCycleRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/powerCycle" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/raise_down.go b/pkg/cloudbroker/compute/raise_down.go new file mode 100644 index 0000000..53f1d78 --- /dev/null +++ b/pkg/cloudbroker/compute/raise_down.go @@ -0,0 +1,24 @@ +package compute + +import ( + "context" + "net/http" + "strconv" +) + +// RaiseDown starting all computes in "DOWN" tech status +func (c Compute) RaiseDown(ctx context.Context) (bool, error) { + url := "/cloudbroker/compute/raiseDown" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, nil) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/reboot.go b/pkg/cloudbroker/compute/reboot.go new file mode 100644 index 0000000..1838d4e --- /dev/null +++ b/pkg/cloudbroker/compute/reboot.go @@ -0,0 +1,49 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for reboot compute +type RebootRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq RebootRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field computeID must be set") + } + + return nil +} + +// Reboot reboot compute +func (c Compute) Reboot(ctx context.Context, req RebootRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/reboot" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/redeploy.go b/pkg/cloudbroker/compute/redeploy.go new file mode 100644 index 0000000..e4d7ef9 --- /dev/null +++ b/pkg/cloudbroker/compute/redeploy.go @@ -0,0 +1,73 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for redeploy +type RedeployRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // ID of the new OS image, if image change is required + // Required: false + ImageID uint64 `url:"imageId,omitempty"` + + // New size for the boot disk in GB, if boot disk size change is required + // Required: false + DiskSize uint64 `url:"diskSize,omitempty"` + + // How to handle data disks connected to this compute instance + // Should be one of: + // - KEEP + // - DETACH + // - DESTROY + // Required: false + DataDisks string `url:"dataDisks,omitempty"` + + // Should the compute be restarted upon successful redeploy + // Required: false + AutoStart bool `url:"autoStart,omitempty"` + + // Set this flag to True to force stop running compute instance and redeploy next + // Required: false + ForceStop bool `url:"forceStop,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq RedeployRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// Redeploy redeploy compute +func (c Compute) Redeploy(ctx context.Context, req RedeployRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/redeploy" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/registration.go b/pkg/cloudbroker/compute/registration.go new file mode 100644 index 0000000..1c4977a --- /dev/null +++ b/pkg/cloudbroker/compute/registration.go @@ -0,0 +1,52 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for set compute registered in RT +type RegistrationRequest struct { + // ID of the Compute + // Required: true + ComputeID uint64 `url:"computeId"` + + // Unique compute registration key + // Required: true + RegistrationKey string `url:"registrationKey"` +} + +func (crq RegistrationRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.RegistrationKey == "" { + return errors.New("validation-error: field RegistrationKey must be set") + } + + return nil +} + +// Registration sets compute registered in RT +func (c Compute) Registration(ctx context.Context, req RegistrationRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/registration" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/repair_boot_fs.go b/pkg/cloudbroker/compute/repair_boot_fs.go new file mode 100644 index 0000000..a12aad6 --- /dev/null +++ b/pkg/cloudbroker/compute/repair_boot_fs.go @@ -0,0 +1,49 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for repair filesystem +type RepairBootFSRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq RepairBootFSRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// RepairBootFS repair compute boot disk filesystem +func (c Compute) RepairBootFS(ctx context.Context, req RepairBootFSRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/repairBootFs" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/reset.go b/pkg/cloudbroker/compute/reset.go new file mode 100644 index 0000000..34075f3 --- /dev/null +++ b/pkg/cloudbroker/compute/reset.go @@ -0,0 +1,49 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for reset compute +type ResetRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq ResetRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// Reset reset compute +func (c Compute) Reset(ctx context.Context, req ResetRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/reset" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/resize.go b/pkg/cloudbroker/compute/resize.go new file mode 100644 index 0000000..38de54a --- /dev/null +++ b/pkg/cloudbroker/compute/resize.go @@ -0,0 +1,63 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for resize compute +type ResizeRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // New CPU count. + // Pass 0 if no change to CPU count is required + // Required: false + Force bool `url:"force,omitempty"` + + // New RAM volume in MB. + // Pass 0 if no change to RAM volume is required + // Required: false + CPU uint64 `url:"cpu,omitempty"` + + // Force compute resize + // Required: false + RAM uint64 `url:"ram,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq ResizeRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// Resize resize compute instance +func (c Compute) Resize(ctx context.Context, req ResizeRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/resize" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/restore.go b/pkg/cloudbroker/compute/restore.go new file mode 100644 index 0000000..f500ffa --- /dev/null +++ b/pkg/cloudbroker/compute/restore.go @@ -0,0 +1,49 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for restore compute +type RestoreRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq RestoreRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// Restore restore compute from recycle bin +func (c Compute) Restore(ctx context.Context, req RestoreRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/restore" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/resume.go b/pkg/cloudbroker/compute/resume.go new file mode 100644 index 0000000..ba56319 --- /dev/null +++ b/pkg/cloudbroker/compute/resume.go @@ -0,0 +1,49 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for resume compute +type ResumeRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq ResumeRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// Resume resume Compute from paused state +func (c Compute) Resume(ctx context.Context, req ResumeRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/resume" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/snapshot_create.go b/pkg/cloudbroker/compute/snapshot_create.go new file mode 100644 index 0000000..f4a8a4c --- /dev/null +++ b/pkg/cloudbroker/compute/snapshot_create.go @@ -0,0 +1,50 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strings" +) + +// Request struct for create snapshot +type SnapshotCreateRequest struct { + // ID of the compute instance to create snapshot for + // Required: true + ComputeID uint64 `url:"computeId"` + + // Text label for snapshot. + // Must be unique among this compute snapshots + // Required: true + Label string `url:"label"` +} + +func (crq SnapshotCreateRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.Label == "" { + return errors.New("validation-error: field Label must be set") + } + + return nil +} + +// SnapshotCreate create compute snapshot +func (c Compute) SnapshotCreate(ctx context.Context, req SnapshotCreateRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/compute/snapshotCreate" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil +} diff --git a/pkg/cloudbroker/compute/snapshot_delete.go b/pkg/cloudbroker/compute/snapshot_delete.go new file mode 100644 index 0000000..efe6652 --- /dev/null +++ b/pkg/cloudbroker/compute/snapshot_delete.go @@ -0,0 +1,52 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete snapshot +type SnapshotDeleteRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Text label of snapshot to delete + // Required: true + Label string `url:"label"` +} + +func (crq SnapshotDeleteRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.Label == "" { + return errors.New("validation-error: field Label must be set") + } + + return nil +} + +// SnapshotDelete delete specified compute snapshot +func (c Compute) SnapshotDelete(ctx context.Context, req SnapshotDeleteRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/snapshotDelete" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/snapshot_evict_disk.go b/pkg/cloudbroker/compute/snapshot_evict_disk.go new file mode 100644 index 0000000..f1b8b6b --- /dev/null +++ b/pkg/cloudbroker/compute/snapshot_evict_disk.go @@ -0,0 +1,52 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for evict specified disk +type SnapshotEvictDiskRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // ID of the disk instance + // Required: true + DiskID uint64 `url:"diskId"` +} + +func (crq SnapshotEvictDiskRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.DiskID == 0 { + return errors.New("validation-error: field DiskID must be set") + } + + return nil +} + +// SnapshotEvictDisk evict specified disk from all snapshots of a compute instance +func (c Compute) SnapshotEvictDisk(ctx context.Context, req SnapshotEvictDiskRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/snapshotEvictDisk" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/snapshot_list.go b/pkg/cloudbroker/compute/snapshot_list.go new file mode 100644 index 0000000..cd5dda5 --- /dev/null +++ b/pkg/cloudbroker/compute/snapshot_list.go @@ -0,0 +1,47 @@ +package compute + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get list snapshots +type SnapshotListRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` +} + +func (crq SnapshotListRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// SnapshotList gets list compute snapshots +func (c Compute) SnapshotList(ctx context.Context, req SnapshotListRequest) (ListSnapshots, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/compute/snapshotList" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListSnapshots{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/compute/snapshot_rollback.go b/pkg/cloudbroker/compute/snapshot_rollback.go new file mode 100644 index 0000000..60cb6be --- /dev/null +++ b/pkg/cloudbroker/compute/snapshot_rollback.go @@ -0,0 +1,52 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for rollback +type SnapshotRollbackRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Text label of snapshot to rollback + // Required: true + Label string `url:"label"` +} + +func (crq SnapshotRollbackRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.Label == "" { + return errors.New("validation-error: field Label must be set") + } + + return nil +} + +// SnapshotRollback rollback specified compute snapshot +func (c Compute) SnapshotRollback(ctx context.Context, req SnapshotRollbackRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/snapshotRollback" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/snapshot_usage.go b/pkg/cloudbroker/compute/snapshot_usage.go new file mode 100644 index 0000000..af28bd1 --- /dev/null +++ b/pkg/cloudbroker/compute/snapshot_usage.go @@ -0,0 +1,54 @@ +package compute + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get compute snapshot real size on storage +type SnapshotUsageRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Specify to show usage exact for this snapshot. + // Leave empty for get usage for all compute snapshots + // Required: false + Label string `url:"label,omitempty"` +} + +func (crq SnapshotUsageRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// SnapshotUsage Get compute snapshot real size on storage. +// Always returns list of json objects, and first json object contains summary about all related +// snapshots. +func (c Compute) SnapshotUsage(ctx context.Context, req SnapshotUsageRequest) (ListSnapshotUsage, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/compute/snapshotUsage" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListSnapshotUsage{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/compute/start.go b/pkg/cloudbroker/compute/start.go new file mode 100644 index 0000000..de71072 --- /dev/null +++ b/pkg/cloudbroker/compute/start.go @@ -0,0 +1,57 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for start compute +type StartRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // ID of CD-ROM live image to boot + // Required: false + AltBootID uint64 `url:"altBootId,omitempty"` + + // ID of stack to start compute + // Required: false + StackID uint64 `url:"stackId,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq StartRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field computeID must be set") + } + + return nil +} + +// Start starts compute +func (c Compute) Start(ctx context.Context, req StartRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/start" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/stop.go b/pkg/cloudbroker/compute/stop.go new file mode 100644 index 0000000..82741cb --- /dev/null +++ b/pkg/cloudbroker/compute/stop.go @@ -0,0 +1,53 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for stop compute +type StopRequest struct { + // ID of compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Force stop compute + // Required: false + Force bool `url:"force,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq StopRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field computeID must be set") + } + + return nil +} + +// Stop stops compute +func (c Compute) Stop(ctx context.Context, req StopRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/stop" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/tag_add.go b/pkg/cloudbroker/compute/tag_add.go new file mode 100644 index 0000000..cb2703d --- /dev/null +++ b/pkg/cloudbroker/compute/tag_add.go @@ -0,0 +1,59 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for add tag to compute +type TagAddRequest struct { + // IDs of the compute instances + // Required: true + ComputeIDs []uint64 `url:"computeIds"` + + // Tag key + // Required: true + Key string `url:"key"` + + // Tag value + // Required: true + Value string `url:"value"` +} + +func (crq TagAddRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeIDs must be set") + } + if crq.Key == "" { + return errors.New("validation-error: field Key must be set") + } + if crq.Value == "" { + return errors.New("validation-error: field Value must be set") + } + + return nil +} + +// TagAdd add tag to compute tags dict +func (c Compute) TagAdd(ctx context.Context, req TagAddRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/tagAdd" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/tag_remove.go b/pkg/cloudbroker/compute/tag_remove.go new file mode 100644 index 0000000..94373f0 --- /dev/null +++ b/pkg/cloudbroker/compute/tag_remove.go @@ -0,0 +1,52 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for remove tag from compute +type TagRemoveRequest struct { + // IDs of the compute instances + // Required: true + ComputeIDs []uint64 `url:"computeIds"` + + // Tag key + // Required: true + Key string `url:"key"` +} + +func (crq TagRemoveRequest) validate() error { + if len(crq.ComputeIDs) == 0 { + return errors.New("validation-error: field ComputeIDs must be set") + } + if crq.Key == "" { + return errors.New("validation-error: field Key must be set") + } + + return nil +} + +// TagRemove removes tag from compute tags dict +func (c Compute) TagRemove(ctx context.Context, req TagRemoveRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/tagRemove" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/unpin_from_stack.go b/pkg/cloudbroker/compute/unpin_from_stack.go new file mode 100644 index 0000000..ae3545d --- /dev/null +++ b/pkg/cloudbroker/compute/unpin_from_stack.go @@ -0,0 +1,45 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for unpin from stack +type UnpinFromStackRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` +} + +func (crq UnpinFromStackRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// UnpinFromStack unpin compute from current stack +func (c Compute) UnpinFromStack(ctx context.Context, req UnpinFromStackRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/unpinFromStack" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/update.go b/pkg/cloudbroker/compute/update.go new file mode 100644 index 0000000..c3d8214 --- /dev/null +++ b/pkg/cloudbroker/compute/update.go @@ -0,0 +1,57 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for update compute +type UpdateRequest struct { + // ID of the compute + // Required: true + ComputeID uint64 `url:"computeId"` + + // New name + // Required: false + Name string `url:"name,omitempty"` + + // New description + // Required: false + Description string `url:"desc,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (crq UpdateRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// Update updates some properties of the compute +func (c Compute) Update(ctx context.Context, req UpdateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/update" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/user_grant.go b/pkg/cloudbroker/compute/user_grant.go new file mode 100644 index 0000000..9ab88fc --- /dev/null +++ b/pkg/cloudbroker/compute/user_grant.go @@ -0,0 +1,69 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" +) + +// Request struct for grant access to compute +type UserGrantRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Name of the user to add + // Required: true + Username string `url:"userName"` + + // Access type + // Should be one of: + // - 'R' for Read only + // - 'RCX' for Write + // - 'ARCXDU' for Admin + // Required: true + AccessType string `url:"accesstype"` +} + +func (crq UserGrantRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.Username == "" { + return errors.New("validation-error: field Username must be set") + } + if crq.AccessType == "" { + return errors.New("validation-error: field AccessType must be set") + } + validator := validators.StringInSlice(crq.AccessType, []string{"R", "RCX", "ARCXDU"}) + if !validator { + return errors.New("validation-error: field AccessType can be only R, RCX or ARCXDU") + } + + return nil +} + +// UserGrant grant user access to the compute +func (c Compute) UserGrant(ctx context.Context, req UserGrantRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/userGrant" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/user_list.go b/pkg/cloudbroker/compute/user_list.go new file mode 100644 index 0000000..b5b0f83 --- /dev/null +++ b/pkg/cloudbroker/compute/user_list.go @@ -0,0 +1,47 @@ +package compute + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get list users for compute +type UserListRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` +} + +func (crq UserListRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + + return nil +} + +// UserList gets users list for compute +func (c Compute) UserList(ctx context.Context, req UserListRequest) (*RecordACL, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/compute/userList" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := RecordACL{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return &list, nil +} diff --git a/pkg/cloudbroker/compute/user_revoke.go b/pkg/cloudbroker/compute/user_revoke.go new file mode 100644 index 0000000..a44c176 --- /dev/null +++ b/pkg/cloudbroker/compute/user_revoke.go @@ -0,0 +1,52 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for revoke user access +type UserRevokeRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Name of the user to remove + // Required: true + Username string `url:"userName"` +} + +func (crq UserRevokeRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.Username == "" { + return errors.New("validation-error: field Username must be set") + } + + return nil +} + +// UserRevoke revokes user access to the compute +func (c Compute) UserRevoke(ctx context.Context, req UserRevokeRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/userRevoke" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/compute/user_update.go b/pkg/cloudbroker/compute/user_update.go new file mode 100644 index 0000000..1411795 --- /dev/null +++ b/pkg/cloudbroker/compute/user_update.go @@ -0,0 +1,69 @@ +package compute + +import ( + "context" + "errors" + "net/http" + "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" +) + +// Request struct for update user access +type UserUpdateRequest struct { + // ID of the compute instance + // Required: true + ComputeID uint64 `url:"computeId"` + + // Name of the user to update + // Required: true + Username string `url:"userName"` + + // Access type + // Should be one of: + // - 'R' for Read only + // - 'RCX' for Write + // - 'ARCXDU' for Admin + // Required: true + AccessType string `url:"accesstype"` +} + +func (crq UserUpdateRequest) validate() error { + if crq.ComputeID == 0 { + return errors.New("validation-error: field ComputeID must be set") + } + if crq.Username == "" { + return errors.New("validation-error: field UserName must be set") + } + if crq.AccessType == "" { + return errors.New("validation-error: field AccessType must be set") + } + validator := validators.StringInSlice(crq.AccessType, []string{"R", "RCX", "ARCXDU"}) + if !validator { + return errors.New("validation-error: field AccessType can be only R, RCX or ARCXDU") + } + + return nil +} + +// UserUpdate updates user access to the compute +func (c Compute) UserUpdate(ctx context.Context, req UserUpdateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/compute/userUpdate" + + res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/computeci.go b/pkg/cloudbroker/computeci.go deleted file mode 100644 index 4ea5f28..0000000 --- a/pkg/cloudbroker/computeci.go +++ /dev/null @@ -1,9 +0,0 @@ -package cloudbroker - -import ( - "github.com/rudecs/decort-sdk/pkg/cloudapi/computeci" -) - -func (cb *CloudBroker) ComputeCI() *computeci.ComputeCI { - return computeci.New(cb.client) -} diff --git a/pkg/cloudbroker/disks.go b/pkg/cloudbroker/disks.go index 8d52c45..08f0901 100644 --- a/pkg/cloudbroker/disks.go +++ b/pkg/cloudbroker/disks.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudbroker/disks" ) +// Accessing the Disks method group func (cb *CloudBroker) Disks() *disks.Disks { return disks.New(cb.client) } diff --git a/pkg/cloudbroker/disks/create.go b/pkg/cloudbroker/disks/create.go index 71c9965..428c61d 100644 --- a/pkg/cloudbroker/disks/create.go +++ b/pkg/cloudbroker/disks/create.go @@ -3,37 +3,68 @@ package disks import ( "context" "errors" - "github.com/rudecs/decort-sdk/internal/validators" "net/http" "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for create disk type CreateRequest struct { - AccountID uint64 `url:"accountId"` - GID uint64 `url:"gid"` - Name string `url:"name"` + // ID of the account + // Required: true + AccountID uint64 `url:"accountId"` + + // ID of the grid (platform) + // Required: true + GID uint64 `url:"gid"` + + // Name of disk + // Required: true + Name string `url:"name"` + + // Description of disk + // Required: false Description string `url:"description,omitempty"` - Size uint64 `url:"size,omitempty"` - Type string `url:"type"` - SSDSize uint64 `url:"ssdSize"` - IOPS uint64 `url:"iops,omitempty"` - SepID uint64 `url:"sepId,omitempty"` - Pool string `url:"pool,omitempty"` + + // Size in GB, default is 0 + // Required: false + Size uint64 `url:"size,omitempty"` + + // Type of disk + // - B=Boot + // - D=Data + // - T=Temp + // Required: true + Type string `url:"type"` + + // Size in GB default is 0 + // Required: false + SSDSize uint64 `url:"ssdSize,omitempty"` + + // Max IOPS disk can perform defaults to 2000 + // Required: false + IOPS uint64 `url:"iops,omitempty"` + + // Storage endpoint provider ID to create disk + // Required: false + SEPID uint64 `url:"sep_id,omitempty"` + + // Pool name to create disk + // Required: false + Pool string `url:"pool,omitempty"` } -func (drq CreateRequest) Validate() error { +func (drq CreateRequest) validate() error { if drq.AccountID == 0 { return errors.New("validation-error: field AccountID must be set") } - if drq.GID == 0 { return errors.New("validation-error: field GID must be set") } - if drq.Name == "" { return errors.New("validation-error: field Name must be set") } - validate := validators.StringInSlice(drq.Type, []string{"B", "D", "T"}) if !validate { return errors.New("validation-error: field must be B, D or T") @@ -42,8 +73,9 @@ func (drq CreateRequest) Validate() error { return nil } +// Create creates a disk func (d Disks) Create(ctx context.Context, req CreateRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } @@ -61,4 +93,4 @@ func (d Disks) Create(ctx context.Context, req CreateRequest) (uint64, error) { } return result, nil -} \ No newline at end of file +} diff --git a/pkg/cloudbroker/disks/delete.go b/pkg/cloudbroker/disks/delete.go index de0982d..3f23e5d 100644 --- a/pkg/cloudbroker/disks/delete.go +++ b/pkg/cloudbroker/disks/delete.go @@ -7,14 +7,26 @@ import ( "strconv" ) +// Request for delete disk type DeleteRequest struct { - DiskID uint64 `url:"diskId"` - Detach bool `url:"detach,omitempty"` - Permanently bool `url:"permanently,omitempty"` - Reason string `url:"reason,omitempty"` + // ID of disk to delete + // Required: true + DiskID uint64 `url:"diskId"` + + // Detach disk from machine first + // Required: false + Detach bool `url:"detach,omitempty"` + + // Whether to completely delete the disk, works only with non attached disks + // Required: false + Permanently bool `url:"permanently,omitempty"` + + // Reason to delete + // Required: false + Reason string `url:"reason,omitempty"` } -func (drq DeleteRequest) Validate() error { +func (drq DeleteRequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID must be set") } @@ -22,8 +34,9 @@ func (drq DeleteRequest) Validate() error { return nil } +// Delete deletes disk by ID func (d Disks) Delete(ctx context.Context, req DeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -41,4 +54,4 @@ func (d Disks) Delete(ctx context.Context, req DeleteRequest) (bool, error) { } return result, nil -} \ No newline at end of file +} diff --git a/pkg/cloudbroker/disks/delete_disks.go b/pkg/cloudbroker/disks/delete_disks.go index 830c8bd..ddd6baa 100644 --- a/pkg/cloudbroker/disks/delete_disks.go +++ b/pkg/cloudbroker/disks/delete_disks.go @@ -7,14 +7,23 @@ import ( "strconv" ) +// Request struct for multiple disks type DeleteDisksRequest struct { - DiskIDS []uint64 `url:"diskIds"` - Reason string `url:"reason"` - Permanently bool `url:"permanently,omitempty"` + // List of disk ids to delete + // Required: true + DisksIDs []uint64 `url:"diskIds"` + + // Reason for deleting the disks + // Required: true + Reason string `url:"reason"` + + // Whether to completely delete the disks, works only with non attached disks + // Required: false + Permanently bool `url:"permanently,omitempty"` } -func (drq DeleteDisksRequest) Validate() error { - if len(drq.DiskIDS) == 0 { +func (drq DeleteDisksRequest) validate() error { + if len(drq.DisksIDs) == 0 { return errors.New("validation-error: field DiskIDs must be set") } if drq.Reason == "" { @@ -24,8 +33,9 @@ func (drq DeleteDisksRequest) Validate() error { return nil } +// DeleteDisks deletes multiple disks permanently func (d Disks) DeleteDisks(ctx context.Context, req DeleteDisksRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/disks/disks.go b/pkg/cloudbroker/disks/disks.go index c79853e..f4a8708 100644 --- a/pkg/cloudbroker/disks/disks.go +++ b/pkg/cloudbroker/disks/disks.go @@ -1,11 +1,14 @@ +// API Actor for managing Disk. This actor is a final API for admin to manage Disk package disks import "github.com/rudecs/decort-sdk/interfaces" +// Structure for creating request to disks type Disks struct { client interfaces.Caller } +// Builder for disks endpoints func New(client interfaces.Caller) *Disks { return &Disks{ client: client, diff --git a/pkg/cloudbroker/disks/get.go b/pkg/cloudbroker/disks/get.go index 0d56856..3ea7695 100644 --- a/pkg/cloudbroker/disks/get.go +++ b/pkg/cloudbroker/disks/get.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get information about disk type GetRequest struct { + // ID of the disk + // Required: true DiskID uint64 `url:"diskId"` } -func (drq GetRequest) Validate() error { +func (drq GetRequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID must be set") } @@ -19,8 +22,10 @@ func (drq GetRequest) Validate() error { return nil } -func (d Disks) Get(ctx context.Context, req GetRequest) (*Disk, error) { - err := req.Validate() +// Get gets disk details +// Notice: the devicename field is the name as it is passed to the kernel (kname in linux) for unattached disks this field has no relevant value +func (d Disks) Get(ctx context.Context, req GetRequest) (*RecordDisk, error) { + err := req.validate() if err != nil { return nil, err } @@ -32,12 +37,12 @@ func (d Disks) Get(ctx context.Context, req GetRequest) (*Disk, error) { return nil, err } - disk := Disk{} + info := RecordDisk{} - err = json.Unmarshal(res, &disk) + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return &disk, nil + return &info, nil } diff --git a/pkg/cloudbroker/disks/limit_io.go b/pkg/cloudbroker/disks/limit_io.go index c58744a..14c4e4b 100644 --- a/pkg/cloudbroker/disks/limit_io.go +++ b/pkg/cloudbroker/disks/limit_io.go @@ -7,25 +7,70 @@ import ( "strconv" ) +// Request struct for limit IO type LimitIORequest struct { - DiskID uint64 `url:"diskId"` - IOPS uint64 `url:"iops,omitempty"` - TotalBytesSec uint64 `url:"total_bytes_sec,omitempty"` - ReadBytesSec uint64 `url:"total_bytes_sec,omitempty"` - WriteBytesSec uint64 `url:"write_bytes_sec,omitempty"` - TotalIOPSSec uint64 `url:"total_iops_sec,omitempty"` - ReadIOPSSec uint64 `url:"read_iops_sec,omitempty"` - WriteIOPSSec uint64 `url:"write_iops_sec,omitempty"` + // ID of the disk to limit + // Required: true + DiskID uint64 `url:"diskId"` + + // Alias for total_iops_sec for backwards compatibility + // Required: false + IOPS uint64 `url:"iops,omitempty"` + + // TotalBytesSec + // Required: false + TotalBytesSec uint64 `url:"total_bytes_sec,omitempty"` + + // ReadBytesSec + // Required: false + ReadBytesSec uint64 `url:"read_bytes_sec,omitempty"` + + // WriteBytesSec + // Required: false + WriteBytesSec uint64 `url:"write_bytes_sec,omitempty"` + + // TotalIOPSSec + // Required: false + TotalIOPSSec uint64 `url:"total_iops_sec,omitempty"` + + // ReadIOPSSec + // Required: false + ReadIOPSSec uint64 `url:"read_iops_sec,omitempty"` + + // WriteIOPSSec + // Required: false + WriteIOPSSec uint64 `url:"write_iops_sec,omitempty"` + + // TotalBytesSecMax + // Required: false TotalBytesSecMax uint64 `url:"total_bytes_sec_max,omitempty"` - ReadBytesSecMax uint64 `url:"read_bytes_sec_max,omitempty"` + + // ReadBytesSecMax + // Required: false + ReadBytesSecMax uint64 `url:"read_bytes_sec_max,omitempty"` + + // WriteBytesSecMax + // Required: false WriteBytesSecMax uint64 `url:"write_bytes_sec_max,omitempty"` - TotalIOPSSecMax uint64 `url:"total_iops_sec_max,omitempty"` - ReadIOPSSecMax uint64 `url:"total_iops_sec_max,omitempty"` - WriteIOPSSecMax uint64 `url:"write_iops_sec_max,omitempty"` - SizeIOPSSec uint64 `url:"size_iops_sec,omitempty"` + + // TotalIOPSSecMax + // Required: false + TotalIOPSSecMax uint64 `url:"total_iops_sec_max,omitempty"` + + // ReadIOPSSecMax + // Required: false + ReadIOPSSecMax uint64 `url:"read_iops_sec_max,omitempty"` + + // WriteIOPSSecMax + // Required: false + WriteIOPSSecMax uint64 `url:"write_iops_sec_max,omitempty"` + + // SizeIOPSSec + // Required: false + SizeIOPSSec uint64 `url:"size_iops_sec,omitempty"` } -func (drq LimitIORequest) Validate() error { +func (drq LimitIORequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID must be set") } @@ -33,14 +78,17 @@ func (drq LimitIORequest) Validate() error { return nil } +// LimitIO limit IO for a certain disk +// total and read/write options are not allowed to be combined +// see http://libvirt.org/formatdomain.html#elementsDisks iotune section for more details func (d Disks) LimitIO(ctx context.Context, req LimitIORequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } url := "/cloudbroker/disks/limitIO" - + res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return false, err @@ -52,4 +100,4 @@ func (d Disks) LimitIO(ctx context.Context, req LimitIORequest) (bool, error) { } return result, nil -} \ No newline at end of file +} diff --git a/pkg/cloudbroker/disks/list.go b/pkg/cloudbroker/disks/list.go index 83a4a08..aeff68c 100644 --- a/pkg/cloudbroker/disks/list.go +++ b/pkg/cloudbroker/disks/list.go @@ -6,13 +6,26 @@ import ( "net/http" ) +// Request struct for get list/list_deleted of disks type ListRequest struct { + // ID of the account the disks belong to + // Required: false AccountID uint64 `url:"accountId,omitempty"` - Type string `url:"type,omitempty"` - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` + + // Type of the disks + // Required: false + Type string `url:"type,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } +// List gets list the created disks belonging to an account func (d Disks) List(ctx context.Context, req ListRequest) (ListDisks, error) { url := "/cloudbroker/disks/list" @@ -21,12 +34,12 @@ func (d Disks) List(ctx context.Context, req ListRequest) (ListDisks, error) { return nil, err } - listDisks := ListDisks{} + list := ListDisks{} - err = json.Unmarshal(res, &listDisks) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return listDisks, nil + return list, nil } diff --git a/pkg/cloudbroker/disks/list_deleted.go b/pkg/cloudbroker/disks/list_deleted.go index 7e12b4e..caf187c 100644 --- a/pkg/cloudbroker/disks/list_deleted.go +++ b/pkg/cloudbroker/disks/list_deleted.go @@ -3,25 +3,29 @@ package disks import ( "context" "encoding/json" - "errors" "net/http" ) +// Request struct for get list deleted disks type ListDeletedRequest struct { - AccountID uint64 `url:"accountId"` - Type string `url:"type,omitempty"` - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` -} + // ID of the account the disks belong to + // Required: false + AccountID uint64 `url:"accountId,omitempty"` -func (drq ListDeletedRequest) Validate() error { - if drq.AccountID == 0 { - return errors.New("validation-error: field AccountID must be set") - } + // Type of the disks + // Required: false + Type string `url:"type,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` - return nil + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } +// ListDeleted gets list the deleted disks based on filter func (d Disks) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListDeletedDisks, error) { url := "/cloudbroker/disks/listDeleted" @@ -30,12 +34,12 @@ func (d Disks) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListDel return nil, err } - deletedDisks := ListDeletedDisks{} + list := ListDeletedDisks{} - err = json.Unmarshal(res, &deletedDisks) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return deletedDisks, nil + return list, nil } diff --git a/pkg/cloudbroker/disks/list_types.go b/pkg/cloudbroker/disks/list_types.go index d9d95a7..fdd41a0 100644 --- a/pkg/cloudbroker/disks/list_types.go +++ b/pkg/cloudbroker/disks/list_types.go @@ -6,10 +6,14 @@ import ( "net/http" ) +// Request struct for get list types of disks type ListTypesRequest struct { + // Show detailed disk types by seps + // Required: false Detailed bool `url:"detailed"` } +// ListTypes gets list defined disk types func (d Disks) ListTypes(ctx context.Context, req ListTypesRequest) ([]interface{}, error) { url := "/cloudbroker/disks/listTypes" @@ -18,13 +22,13 @@ func (d Disks) ListTypes(ctx context.Context, req ListTypesRequest) ([]interface return nil, err } - typesList := make([]interface{}, 0) + list := make([]interface{}, 0) - err = json.Unmarshal(res, &typesList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return typesList, nil + return list, nil } diff --git a/pkg/cloudbroker/disks/list_unattached.go b/pkg/cloudbroker/disks/list_unattached.go index 7cba2cb..54c8c9a 100644 --- a/pkg/cloudbroker/disks/list_unattached.go +++ b/pkg/cloudbroker/disks/list_unattached.go @@ -3,23 +3,26 @@ package disks import ( "context" "encoding/json" - "errors" "net/http" ) +// Request struct for get list unattached disk type ListUnattachedRequest struct { - AccountID uint64 `url:"accountId"` -} + // ID of the account + // Required: false + AccountID uint64 `url:"accountId,omitempty"` -func (drq ListUnattachedRequest) Validate() error { - if drq.AccountID == 0 { - return errors.New("validation-error: field AccountID can not be empty or equal to 0") - } + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` - return nil + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (d Disks) ListUnattached(ctx context.Context, req ListUnattachedRequest) (ListUnattached, error) { +// ListUnattached gets list of unattached disks +func (d Disks) ListUnattached(ctx context.Context, req ListUnattachedRequest) (ListUnattachedDisks, error) { url := "/cloudbroker/disks/listUnattached" res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req) @@ -27,13 +30,12 @@ func (d Disks) ListUnattached(ctx context.Context, req ListUnattachedRequest) (L return nil, err } - diskList := ListUnattached{} + list := ListUnattachedDisks{} - err = json.Unmarshal(res, &diskList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return diskList, nil - + return list, nil } diff --git a/pkg/cloudbroker/disks/models.go b/pkg/cloudbroker/disks/models.go index 76978b1..dd0082f 100644 --- a/pkg/cloudbroker/disks/models.go +++ b/pkg/cloudbroker/disks/models.go @@ -1,101 +1,271 @@ package disks +// Main information about IO tune type IOTune struct { - ReadBytesSec uint64 `json:"read_bytes_sec"` - ReadBytesSecMax uint64 `json:"read_bytes_sec_max"` - ReadIOPSSec uint64 `json:"read_iops_sec"` - ReadIOPSSecMax uint64 `json:"read_iops_sec_max"` - SizeIOPSSec uint64 `json:"size_iops_sec"` - TotalBytesSec uint64 `json:"total_bytes_sec"` + // ReadBytesSec + ReadBytesSec uint64 `json:"read_bytes_sec"` + + // ReadBytesSecMax + ReadBytesSecMax uint64 `json:"read_bytes_sec_max"` + + // ReadIOPSSec + ReadIOPSSec uint64 `json:"read_iops_sec"` + + // ReadIOPSSecMax + ReadIOPSSecMax uint64 `json:"read_iops_sec_max"` + + // SizeIOPSSec + SizeIOPSSec uint64 `json:"size_iops_sec"` + + // TotalBytesSec + TotalBytesSec uint64 `json:"total_bytes_sec"` + + // TotalBytesSecMax TotalBytesSecMax uint64 `json:"total_bytes_sec_max"` - TotalIOPSSec uint64 `json:"total_iops_sec"` - TotalIOPSSecMax uint64 `json:"total_iops_sec_max"` - WriteBytesSec uint64 `json:"write_bytes_sec"` + + // TotalIOPSSec + TotalIOPSSec uint64 `json:"total_iops_sec"` + + // TotalIOPSSecMax + TotalIOPSSecMax uint64 `json:"total_iops_sec_max"` + + // WriteBytesSec + WriteBytesSec uint64 `json:"write_bytes_sec"` + + // WriteBytesSecMax WriteBytesSecMax uint64 `json:"write_bytes_sec_max"` - WriteIOPSSec uint64 `json:"write_iops_sec"` - WriteIOPSSecMax uint64 `json:"write_iops_sec_max"` + + // WriteIOPSSec + WriteIOPSSec uint64 `json:"write_iops_sec"` + + // WriteIOPSSecMax + WriteIOPSSecMax uint64 `json:"write_iops_sec_max"` } -type Info struct { - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - ACL map[string]interface{} `json:"acl"` - BootPartition uint64 `json:"bootPartition"` - CreatedTime uint64 `json:"createdTime"` - DeletedTime uint64 `json:"deletedTime"` - Desc string `json:"desc"` - DestructionTime uint64 `json:"destructionTime"` - DiskPath string `json:"diskPath"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - ImageID uint64 `json:"imageId"` - Images []uint64 `json:"images"` - IOTune IOTune `json:"iotune"` - Iqn string `json:"iqn"` - Login string `json:"login"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - Order uint64 `json:"order"` - Params string `json:"params"` - ParentID uint64 `json:"parentId"` - Passwd string `json:"passwd"` - PCISlot int64 `json:"pciSlot"` - Pool string `json:"pool"` - PurgeAttempts uint64 `json:"purgeAttempts"` - PurgeTime uint64 `json:"purgeTime"` - RealityDeviceNumber uint64 `json:"realityDeviceNumber"` - ReferenceID string `json:"referenceId"` - ResID string `json:"resId"` - ResName string `json:"resName"` - Role string `json:"role"` - SepID uint64 `json:"sepId"` - SizeMax uint64 `json:"sizeMax"` - SizeUsed uint64 `json:"sizeUsed"` - Snapshots []Snapshot `json:"snapshots"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - Type string `json:"type"` - VMID uint64 `json:"vmid"` +// Main information about disks +type InfoDisk struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Access Control Control + ACL map[string]interface{} `json:"acl"` + + // Boot partition + BootPartition uint64 `json:"bootPartition"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // Destruction time + DestructionTime uint64 `json:"destructionTime"` + + // Disk path + DiskPath string `json:"diskPath"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Image ID + ImageID uint64 `json:"imageId"` + + // List of image IDs + Images []uint64 `json:"images"` + + // IOTune + IOTune IOTune `json:"iotune"` + + // IQN + IQN string `json:"iqn"` + + // Login + Login string `json:"login"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Order + Order uint64 `json:"order"` + + // Params + Params string `json:"params"` + + // Parent ID + ParentID uint64 `json:"parentId"` + + // Password + Password string `json:"passwd"` + + // PCI slot + PCISlot int64 `json:"pciSlot"` + + // Pool + Pool string `json:"pool"` + + // Purge attempts + PurgeAttempts uint64 `json:"purgeAttempts"` + + // Purge time + PurgeTime uint64 `json:"purgeTime"` + + // Reality device number + RealityDeviceNumber uint64 `json:"realityDeviceNumber"` + + // Reference ID + ReferenceID string `json:"referenceId"` + + // Resource ID + ResID string `json:"resId"` + + // Resource name + ResName string `json:"resName"` + + // Role + Role string `json:"role"` + + // SEP ID + SEPID uint64 `json:"sepId"` + + // Size max + SizeMax uint64 `json:"sizeMax"` + + // Size used + SizeUsed uint64 `json:"sizeUsed"` + + // List snapshots + Snapshots ListSnapshots `json:"snapshots"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Type + Type string `json:"type"` + + // Virtual machine ID + VMID uint64 `json:"vmid"` } -type Disk struct { +// Detailed indormation about disk +type RecordDisk struct { + // Device name DeviceName string `json:"devicename"` - SepType string `json:"sepType"` - Info + + // SEP type + SEPType string `json:"sepType"` + + // Main information about disk + InfoDisk } -type ListDisks []struct { - ComputeID uint64 `json:"computeId"` +// Main information for list disks +type ItemDisk struct { + // Compute ID + ComputeID uint64 `json:"computeId"` + + // Compute name ComputeName string `json:"computeName"` - MachineID uint64 `json:"machineId"` + + // Machine ID + MachineID uint64 `json:"machineId"` + + // Machine name MachineName string `json:"machineName"` - Disk + + // Detailed information about disk + RecordDisk } -type ListDeletedDisks []struct { - ComputeID uint64 `json:"computeId"` +// List disks +type ListDisks []ItemDisk + +// Main information about deleted disk +type ItemDeletedDisk struct { + // Compute ID + ComputeID uint64 `json:"computeId"` + + // Compute name ComputeName string `json:"computeName"` - MachineID uint64 `json:"machineId"` + + // Machine ID + MachineID uint64 `json:"machineId"` + + // Machine name MachineName string `json:"machineName"` - Disk - UpdatedBy uint64 `json:"updatedBy"` + + // Detailed information about disk + RecordDisk + + // Updated by + UpdatedBy uint64 `json:"updatedBy"` + + // Updated time UpdatedTime uint64 `json:"updatedTime"` } -type ListUnattached []struct { - CKey string `json:"_ckey"` +// List deleted disks +type ListDeletedDisks []ItemDeletedDisk + +// Main information about unattached disk +type ItemUnattachedDisk struct { + // CKey + CKey string `json:"_ckey"` + + // Meta Meta []interface{} `json:"_meta"` - Info - UpdatedBy uint64 `json:"updatedBy"` + + // Main information about disk + InfoDisk + + // Updated by + UpdatedBy uint64 `json:"updatedBy"` + + // Updated time UpdatedTime uint64 `json:"updatedTime"` } -type Snapshot struct { - GUID string `json:"guid"` - Label string `json:"label"` - ResID string `json:"resId"` +// List unattached disks +type ListUnattachedDisks []ItemUnattachedDisk + +// Main information about snapshot +type ItemSnapshot struct { + // GUID + GUID string `json:"guid"` + + // Label + Label string `json:"label"` + + // Resource ID + ResID string `json:"resId"` + + // SnapSet GUID SnapSetGUID string `json:"snapSetGuid"` + + // SnapSet time SnapSetTime uint64 `json:"snapSetTime"` - Timestamp uint64 `json:"timestamp"` + + // Timestamp + Timestamp uint64 `json:"timestamp"` } + +// List snapshots +type ListSnapshots []ItemSnapshot diff --git a/pkg/cloudbroker/disks/rename.go b/pkg/cloudbroker/disks/rename.go index 2e6f499..66b3645 100644 --- a/pkg/cloudbroker/disks/rename.go +++ b/pkg/cloudbroker/disks/rename.go @@ -7,16 +7,21 @@ import ( "strconv" ) +// Request struct for rename disk type RenameRequest struct { + // ID of the disk to rename + // Required: true DiskID uint64 `url:"diskId"` - Name string `url:"name"` + + // New name of disk + // Required: true + Name string `url:"name"` } -func (drq RenameRequest) Validate() error { +func (drq RenameRequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID must be set") } - if drq.Name == "" { return errors.New("validation-error: field Name must be set") } @@ -24,8 +29,9 @@ func (drq RenameRequest) Validate() error { return nil } +// Rename rename disk func (d Disks) Rename(ctx context.Context, req RenameRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -43,5 +49,4 @@ func (d Disks) Rename(ctx context.Context, req RenameRequest) (bool, error) { } return result, nil - } diff --git a/pkg/cloudbroker/disks/resize.go b/pkg/cloudbroker/disks/resize.go index 141dbbf..274ec21 100644 --- a/pkg/cloudbroker/disks/resize.go +++ b/pkg/cloudbroker/disks/resize.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for resize disk type ResizeRequest struct { + // ID of the disk to resize + // Required: true DiskID uint64 `url:"diskId"` - Size uint64 `url:"size"` + + // New size of the disk in GB + // Required: true + Size uint64 `url:"size"` } -func (drq ResizeRequest) Validate() error { +func (drq ResizeRequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID must be set") } @@ -22,8 +28,12 @@ func (drq ResizeRequest) Validate() error { return nil } +// Resize resize disk +// Returns 200 if disk is resized online, else will return 202, +// in that case please stop and start your machine after changing the disk size, for your changes to be reflected. +// This method will not be used for disks, assigned to computes. Only unassigned disks and disks, assigned with "old" virtual machines. func (d Disks) Resize(ctx context.Context, req ResizeRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -41,11 +51,14 @@ func (d Disks) Resize(ctx context.Context, req ResizeRequest) (bool, error) { } return result, nil - } +// Resize2 resize disk +// Returns 200 if disk is resized online, else will return 202, +// in that case please stop and start your machine after changing the disk size, for your changes to be reflected. +// This method will not be used for disks, assigned to "old" virtual machines. Only unassigned disks and disks, assigned with computes. func (d Disks) Resize2(ctx context.Context, req ResizeRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -63,5 +76,4 @@ func (d Disks) Resize2(ctx context.Context, req ResizeRequest) (bool, error) { } return result, nil - } diff --git a/pkg/cloudbroker/disks/restore.go b/pkg/cloudbroker/disks/restore.go index 1fbf982..ebd5695 100644 --- a/pkg/cloudbroker/disks/restore.go +++ b/pkg/cloudbroker/disks/restore.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for restore a deleted unattached disk type RestoreRequest struct { + // ID of the disk to restore + // Required: true DiskID uint64 `url:"diskId"` + + // Reason for restoring the disk + // Required: true Reason string `url:"reason"` } -func (drq RestoreRequest) Validate() error { +func (drq RestoreRequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID must be set") } @@ -23,8 +29,9 @@ func (drq RestoreRequest) Validate() error { return nil } +// Restore restore a deleted unattached disk from recycle bin func (d Disks) Restore(ctx context.Context, req RestoreRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -42,5 +49,4 @@ func (d Disks) Restore(ctx context.Context, req RestoreRequest) (bool, error) { } return result, nil - } diff --git a/pkg/cloudbroker/disks/search.go b/pkg/cloudbroker/disks/search.go index 8f39aaf..28d3e3b 100644 --- a/pkg/cloudbroker/disks/search.go +++ b/pkg/cloudbroker/disks/search.go @@ -6,14 +6,29 @@ import ( "net/http" ) +// Request struct for search type SearchRequest struct { + // ID of the account to search for the Disk + // Required: false AccountID uint64 `url:"accountId,omitempty"` - Name string `url:"name,omitempty"` - ShowAll bool `url:"show_all,omitempty"` - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` + // Name of the Disk to search for + // Required: false + Name string `url:"name,omitempty"` + + // If false, then disks having one of the statuses are not listed + // Required: false + ShowAll bool `url:"show_all,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } +// Search search disks func (d Disks) Search(ctx context.Context, req SearchRequest) (ListDisks, error) { url := "/cloudbroker/disks/search" @@ -22,13 +37,12 @@ func (d Disks) Search(ctx context.Context, req SearchRequest) (ListDisks, error) return nil, err } - diskList := ListDisks{} + list := ListDisks{} - err = json.Unmarshal(res, &diskList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return diskList, nil - + return list, nil } diff --git a/pkg/cloudbroker/disks/snapshot_delete.go b/pkg/cloudbroker/disks/snapshot_delete.go index 03de522..6b8d091 100644 --- a/pkg/cloudbroker/disks/snapshot_delete.go +++ b/pkg/cloudbroker/disks/snapshot_delete.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for delete snapshot type SnapshotDeleteRequest struct { + // ID of disk to delete + // Required: true DiskID uint64 `url:"diskId"` - Label string `url:"label"` + + // Label of the snapshot to delete + // Required: false + Label string `url:"label"` } -func (drq SnapshotDeleteRequest) Validate() error { +func (drq SnapshotDeleteRequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID must be set") } @@ -23,8 +29,9 @@ func (drq SnapshotDeleteRequest) Validate() error { return nil } +// SnapshotDelete deletes a snapshot func (d Disks) SnapshotDelete(ctx context.Context, req SnapshotDeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -42,5 +49,4 @@ func (d Disks) SnapshotDelete(ctx context.Context, req SnapshotDeleteRequest) (b } return result, nil - } diff --git a/pkg/cloudbroker/disks/snapshot_rollback.go b/pkg/cloudbroker/disks/snapshot_rollback.go index 4908b6d..c365365 100644 --- a/pkg/cloudbroker/disks/snapshot_rollback.go +++ b/pkg/cloudbroker/disks/snapshot_rollback.go @@ -7,13 +7,22 @@ import ( "strconv" ) +// Request struct for rollback snapshot type SnapshotRollbackRequest struct { - DiskID uint64 `url:"diskId"` - Label string `url:"label"` + // ID of the disk + // Required: true + DiskID uint64 `url:"diskId"` + + // Label of the snapshot to rollback + // Required: true + Label string `url:"label"` + + // Timestamp of the snapshot to rollback + // Required: true TimeStamp uint64 `url:"timestamp"` } -func (drq SnapshotRollbackRequest) Validate() error { +func (drq SnapshotRollbackRequest) validate() error { if drq.DiskID == 0 { return errors.New("validation-error: field DiskID must be set") } @@ -27,8 +36,9 @@ func (drq SnapshotRollbackRequest) Validate() error { return nil } +// SnapshotRollback rollback an individual disk snapshot func (d Disks) SnapshotRollback(ctx context.Context, req SnapshotRollbackRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -46,5 +56,4 @@ func (d Disks) SnapshotRollback(ctx context.Context, req SnapshotRollbackRequest } return result, nil - } diff --git a/pkg/cloudbroker/extnet.go b/pkg/cloudbroker/extnet.go index 7eac5ff..eb360f9 100644 --- a/pkg/cloudbroker/extnet.go +++ b/pkg/cloudbroker/extnet.go @@ -1,9 +1,10 @@ package cloudbroker import ( - "github.com/rudecs/decort-sdk/pkg/cloudapi/extnet" + "github.com/rudecs/decort-sdk/pkg/cloudbroker/extnet" ) +// Accessing the ExtNet method group func (cb *CloudBroker) ExtNet() *extnet.ExtNet { return extnet.New(cb.client) } diff --git a/pkg/cloudbroker/extnet/access_add.go b/pkg/cloudbroker/extnet/access_add.go new file mode 100644 index 0000000..a36785d --- /dev/null +++ b/pkg/cloudbroker/extnet/access_add.go @@ -0,0 +1,54 @@ +package extnet + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for grant access +type AccessAddRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` + + // Account ID + // Required: true + AccountID uint64 `url:"accountId"` +} + +func (erq AccessAddRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + if erq.AccountID == 0 { + return errors.New("validation-error: field AccountID must be set") + } + + return nil +} + +// AccessAdd grant access to external network for account ID +func (e ExtNet) AccessAdd(ctx context.Context, req AccessAddRequest) ([]uint64, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/extnet/accessAdd" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := make([]uint64, 0) + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/extnet/access_remove.go b/pkg/cloudbroker/extnet/access_remove.go new file mode 100644 index 0000000..aee0dce --- /dev/null +++ b/pkg/cloudbroker/extnet/access_remove.go @@ -0,0 +1,54 @@ +package extnet + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for remove access +type AccessRemoveRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` + + // Account ID + // Required: true + AccountID uint64 `url:"accountId"` +} + +func (erq AccessRemoveRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + if erq.AccountID == 0 { + return errors.New("validation-error: field AccountID must be set") + } + + return nil +} + +// AccessRemove remove access from external network for account ID +func (e ExtNet) AccessRemove(ctx context.Context, req AccessRemoveRequest) ([]uint64, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/extnet/accessRemove" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := make([]uint64, 0) + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/extnet/create.go b/pkg/cloudbroker/extnet/create.go new file mode 100644 index 0000000..c964488 --- /dev/null +++ b/pkg/cloudbroker/extnet/create.go @@ -0,0 +1,114 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for create external network +type CreateRequest struct { + // External network name + // Required: true + Name string `url:"name"` + + // Grid (platform) ID + // Required: true + GID uint64 `url:"gid"` + + // IP network CIDR + // For example 192.168.0.0/24 + // Required: true + IPCIDR string `url:"ipcidr"` + + // External network gateway IP address + // Required: true + Gateway string `url:"gateway"` + + // VLAN ID + // Required: true + VLANID uint64 `url:"vlanId"` + + // List of DNS addresses + // Required: false + DNS []string `url:"dns,omitempty"` + + // List of NTP addresses + // Required: false + NTP []string `url:"ntp,omitempty"` + + // IPs to check network availability + // Required: false + CheckIPs []string `url:"checkIps,omitempty"` + + // If true - platform DHCP server will not be created + // Required: false + Virtual bool `url:"virtual,omitempty"` + + // Optional description + // Required: false + Description string `url:"desc,omitempty"` + + // Start of IP range to be explicitly included + // Required: false + StartIP string `url:"startIP,omitempty"` + + // End of IP range to be explicitly included + // Required: false + EndIP string `url:"endIP,omitempty"` + + // IP to create VNFDev with + // Required: false + VNFDevIP string `url:"vnfdevIP,omitempty"` + + // Number of pre created reservations + // Required: false + PreReservationsNum uint64 `url:"preReservationsNum,omitempty"` + + // OpenvSwith bridge name for ExtNet connection + // Required: false + OVSBridge string `url:"ovsBridge,omitempty"` +} + +func (erq CreateRequest) validate() error { + if erq.Name == "" { + return errors.New("validation-error: field Name must be set") + } + if erq.GID == 0 { + return errors.New("validation-error: field GID must be set") + } + if erq.IPCIDR == "" { + return errors.New("validation-error: field IPCIDR must be set") + } + if erq.Gateway == "" { + return errors.New("validation-error: field Gateway must be set") + } + if erq.VLANID == 0 { + return errors.New("validation-error: field VLANID must be set") + } + + return nil +} + +// Create creates new external network into platform +func (e ExtNet) Create(ctx context.Context, req CreateRequest) (uint64, error) { + err := req.validate() + if err != nil { + return 0, err + } + + url := "/cloudbroker/extnet/create" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/default_qos_update.go b/pkg/cloudbroker/extnet/default_qos_update.go new file mode 100644 index 0000000..339b74f --- /dev/null +++ b/pkg/cloudbroker/extnet/default_qos_update.go @@ -0,0 +1,57 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for update QOS +type DefaultQOSUpdateRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` + + // Internal traffic, kbit + // Required: false + IngressRate uint64 `url:"ingress_rate,omitempty"` + + // Internal traffic burst, kbit + // Required: false + IngressBurst uint64 `url:"ingress_burst,omitempty"` + + // External traffic rate, kbit + // Required: false + EgressRate uint64 `url:"egress_rate,omitempty"` +} + +func (erq DefaultQOSUpdateRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// DefaultQOSUpdate updates default qos values +func (e ExtNet) DefaultQOSUpdate(ctx context.Context, req DefaultQOSUpdateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/defaultQosUpdate" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/destroy.go b/pkg/cloudbroker/extnet/destroy.go new file mode 100644 index 0000000..c7f47a2 --- /dev/null +++ b/pkg/cloudbroker/extnet/destroy.go @@ -0,0 +1,45 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for destroy +type DestroyRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` +} + +func (erq DestroyRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// Destroy destroys external network +func (e ExtNet) Destroy(ctx context.Context, req DestroyRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/destroy" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/device_deploy.go b/pkg/cloudbroker/extnet/device_deploy.go new file mode 100644 index 0000000..7bf250d --- /dev/null +++ b/pkg/cloudbroker/extnet/device_deploy.go @@ -0,0 +1,45 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for deploy network device +type DeviceDeployRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` +} + +func (erq DeviceDeployRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// DeviceDeploy deploys network device for external network (make not virtual, "physical") +func (e ExtNet) DeviceDeploy(ctx context.Context, req DeviceDeployRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/deviceDeploy" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/device_migrate.go b/pkg/cloudbroker/extnet/device_migrate.go new file mode 100644 index 0000000..8d99ed0 --- /dev/null +++ b/pkg/cloudbroker/extnet/device_migrate.go @@ -0,0 +1,45 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for migrate VNF +type DeviceMigrateRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` +} + +func (erq DeviceMigrateRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// DeviceMigrate migrate external network VNF device +func (e ExtNet) DeviceMigrate(ctx context.Context, req DeviceMigrateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/deviceMigrate" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/device_remove.go b/pkg/cloudbroker/extnet/device_remove.go new file mode 100644 index 0000000..6eea2ee --- /dev/null +++ b/pkg/cloudbroker/extnet/device_remove.go @@ -0,0 +1,45 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for remove network device +type DeviceRemoveRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` +} + +func (erq DeviceRemoveRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// DeviceRemove removes network device of external network (make it virtual, not "physical") +func (e ExtNet) DeviceRemove(ctx context.Context, req DeviceRemoveRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/deviceRemove" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/device_restart.go b/pkg/cloudbroker/extnet/device_restart.go new file mode 100644 index 0000000..54826c6 --- /dev/null +++ b/pkg/cloudbroker/extnet/device_restart.go @@ -0,0 +1,45 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for restart VNF device +type DeviceRestartRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` +} + +func (erq DeviceRestartRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// DeviceRestart restarts external network VNF device +func (e ExtNet) DeviceRestart(ctx context.Context, req DeviceRestartRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/deviceRestart" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/disable.go b/pkg/cloudbroker/extnet/disable.go new file mode 100644 index 0000000..3bd25ea --- /dev/null +++ b/pkg/cloudbroker/extnet/disable.go @@ -0,0 +1,45 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for disable external network +type DisableRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` +} + +func (erq DisableRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// Disable disables external network +func (e ExtNet) Disable(ctx context.Context, req DisableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/disable" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/dns_apply.go b/pkg/cloudbroker/extnet/dns_apply.go new file mode 100644 index 0000000..abeaca5 --- /dev/null +++ b/pkg/cloudbroker/extnet/dns_apply.go @@ -0,0 +1,49 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for set new DNS +type DNSApplyRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` + + // List of DNS to apply + // Required: false + DNSList []string `url:"dns_list,omitempty"` +} + +func (erq DNSApplyRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// DNSApply sets new DNS +func (e ExtNet) DNSApply(ctx context.Context, req DNSApplyRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/dnsApply" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/enable.go b/pkg/cloudbroker/extnet/enable.go new file mode 100644 index 0000000..97e922d --- /dev/null +++ b/pkg/cloudbroker/extnet/enable.go @@ -0,0 +1,45 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for enable external network +type EnableRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` +} + +func (erq EnableRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// Enable enables external networks +func (e ExtNet) Enable(ctx context.Context, req EnableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/enable" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/extnet.go b/pkg/cloudbroker/extnet/extnet.go new file mode 100644 index 0000000..1187f35 --- /dev/null +++ b/pkg/cloudbroker/extnet/extnet.go @@ -0,0 +1,16 @@ +// API Actor for configure and use external networks +package extnet + +import "github.com/rudecs/decort-sdk/interfaces" + +// Structure for creating request to extnet +type ExtNet struct { + client interfaces.Caller +} + +// Builder for extnet endpoints +func New(client interfaces.Caller) *ExtNet { + return &ExtNet{ + client: client, + } +} diff --git a/pkg/cloudbroker/extnet/get.go b/pkg/cloudbroker/extnet/get.go new file mode 100644 index 0000000..4fc2b7c --- /dev/null +++ b/pkg/cloudbroker/extnet/get.go @@ -0,0 +1,47 @@ +package extnet + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get information about external network +type GetRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` +} + +func (erq GetRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// Get gets external network details +func (e ExtNet) Get(ctx context.Context, req GetRequest) (*RecordExtNet, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/extnet/get" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + info := RecordExtNet{} + + err = json.Unmarshal(res, &info) + if err != nil { + return nil, err + } + + return &info, nil +} diff --git a/pkg/cloudbroker/extnet/get_default.go b/pkg/cloudbroker/extnet/get_default.go new file mode 100644 index 0000000..1285d22 --- /dev/null +++ b/pkg/cloudbroker/extnet/get_default.go @@ -0,0 +1,24 @@ +package extnet + +import ( + "context" + "net/http" + "strconv" +) + +// GetDefault get default external network ID +func (e ExtNet) GetDefault(ctx context.Context) (uint64, error) { + url := "/cloudbroker/extnet/getDefault" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, nil) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/ips_exclude.go b/pkg/cloudbroker/extnet/ips_exclude.go new file mode 100644 index 0000000..665ec99 --- /dev/null +++ b/pkg/cloudbroker/extnet/ips_exclude.go @@ -0,0 +1,52 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for exclude list IPs +type IPsExcludeRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` + + // List of IPs for exclude from external network + // Required: true + IPs []string `url:"ips"` +} + +func (erq IPsExcludeRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + if len(erq.IPs) == 0 { + return errors.New("validation-error: field IPs must be set") + } + + return nil +} + +// IPsExclude exclude list IPs from external network pool +func (e ExtNet) IPsExclude(ctx context.Context, req IPsExcludeRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/ipsExclude" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/ips_exclude_range.go b/pkg/cloudbroker/extnet/ips_exclude_range.go new file mode 100644 index 0000000..b5462ab --- /dev/null +++ b/pkg/cloudbroker/extnet/ips_exclude_range.go @@ -0,0 +1,59 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for exclude range of IPs +type IPsExcludeRangeRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` + + // Starting IP + // Required: true + IPStart string `url:"ip_start"` + + // Ending IP + // Required: true + IPEnd string `url:"ip_end"` +} + +func (erq IPsExcludeRangeRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + if erq.IPStart == "" { + return errors.New("validation-error: field IPStart must be set") + } + if erq.IPEnd == "" { + return errors.New("validation-error: field IPEnd must be set") + } + + return nil +} + +// IPsExcludeRange exclude range of IPs from external network pool +func (e ExtNet) IPsExcludeRange(ctx context.Context, req IPsExcludeRangeRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/ipsExcludeRange" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/ips_include.go b/pkg/cloudbroker/extnet/ips_include.go new file mode 100644 index 0000000..ea35adc --- /dev/null +++ b/pkg/cloudbroker/extnet/ips_include.go @@ -0,0 +1,52 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for include list IPs +type IPsIncludeRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` + + // List of IPs for include to external network + // Required: true + IPs []string `url:"ips"` +} + +func (erq IPsIncludeRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + if len(erq.IPs) == 0 { + return errors.New("validation-error: field IPs must be set") + } + + return nil +} + +// IPsInclude include list IPs to external network pool +func (e ExtNet) IPsInclude(ctx context.Context, req IPsIncludeRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/ipsInclude" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/ips_include_range.go b/pkg/cloudbroker/extnet/ips_include_range.go new file mode 100644 index 0000000..81dbabd --- /dev/null +++ b/pkg/cloudbroker/extnet/ips_include_range.go @@ -0,0 +1,59 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for include range of IPs +type IPsIncludeRangeRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` + + // Starting IP + // Required: true + IPStart string `url:"ip_start"` + + // Ending IP + // Required: true + IPEnd string `url:"ip_end"` +} + +func (erq IPsIncludeRangeRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + if erq.IPStart == "" { + return errors.New("validation-error: field IPStart must be set") + } + if erq.IPEnd == "" { + return errors.New("validation-error: field IPEnd must be set") + } + + return nil +} + +// IPsIncludeRange include range of IPs to external network pool +func (e ExtNet) IPsIncludeRange(ctx context.Context, req IPsIncludeRangeRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/ipsIncludeRange" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/list.go b/pkg/cloudbroker/extnet/list.go new file mode 100644 index 0000000..898946c --- /dev/null +++ b/pkg/cloudbroker/extnet/list.go @@ -0,0 +1,41 @@ +package extnet + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get list external network +type ListRequest struct { + // Filter by account ID + // Required: false + AccountID uint64 `url:"accountId,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} + +// List gets list all available external networks +func (e ExtNet) List(ctx context.Context, req ListRequest) (ListExtNet, error) { + url := "/cloudbroker/extnet/list" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListExtNet{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/extnet/models.go b/pkg/cloudbroker/extnet/models.go new file mode 100644 index 0000000..8d9445b --- /dev/null +++ b/pkg/cloudbroker/extnet/models.go @@ -0,0 +1,147 @@ +package extnet + +// QOS +type QOS struct { + // ERate + ERate uint64 `json:"eRate"` + + // GUID + GUID string `json:"guid"` + + // InBurst + InBurst uint64 `json:"inBurst"` + + // InRate + InRate uint64 `json:"inRate"` +} + +// Main information about reservations +type ItemReservation struct { + // Client type + ClientType string `json:"clientType"` + + // Description + Description string `json:"desc"` + + // IP + IP string `json:"ip"` + + // MAC + MAC string `json:"mac"` + + // Type + Type string `json:"type"` + + // Virtual machine ID + VMID uint64 `json:"vmId"` + + // Domain name + DomainName string `json:"domainname"` + + // Hostname + Hostname string `json:"hostname"` +} + +// List reservations +type ListReservations []ItemReservation + +// VNFs +type VNFs struct { + DHCP int `json:"dhcp"` +} + +// Main information about external network +type ItemExtNet struct { + // CKey + CKey string `json:"_ckey"` + + // Meta + Meta []interface{} `json:"_meta"` + + // CheckIPs + CheckIPs []string `json:"checkIps"` + + // Default + Default bool `json:"default"` + + // Default QOS + DefaultQOS QOS `json:"defaultQos"` + + // Description + Description string `json:"desc"` + + // Free IPs number + FreeIPs uint64 `json:"freeIps"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // IPCIDR + IPCIDR string `json:"ipcidr"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Network ID + NetworkID uint64 `json:"networkId"` + + // OVSBridge + OVSBridge string `json:"ovsBridge"` + + // PreReservationsNum + PreReservationsNum uint64 `json:"preReservationsNum"` + + // PriVNFDevID + PriVNFDevID uint64 `json:"priVnfDevId"` + + // List of shared with + SharedWith []interface{} `json:"sharedWith"` + + // Status + Status string `json:"status"` + + // VLAN ID + VLANID uint64 `json:"vlanId"` + + // VNFs + VNFs VNFs `json:"vnfs"` +} + +// List external networks +type ListExtNet []ItemExtNet + +// Detailed information about external network +type RecordExtNet struct { + // Main information about external network + ItemExtNet + + // CheckIPs + CheckIPs []string `json:"checkIPs"` + + // List DNS + DNS []string `json:"dns"` + + // List excludes + Excluded []string `json:"excluded"` + + // Gateway + Gateway string `json:"gateway"` + + // Network + Network string `json:"network"` + + // Prefix + Prefix uint64 `json:"prefix"` + + // List reservations + Reservations ListReservations `json:"reservations"` +} diff --git a/pkg/cloudbroker/extnet/ntp_apply.go b/pkg/cloudbroker/extnet/ntp_apply.go new file mode 100644 index 0000000..164a239 --- /dev/null +++ b/pkg/cloudbroker/extnet/ntp_apply.go @@ -0,0 +1,49 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for set new NTP +type NTPApplyRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` + + // List of NTP to apply + // Required: false + NTPList []string `url:"ntp_list,omitempty"` +} + +func (erq NTPApplyRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// NTPApply sets new NTP +func (e ExtNet) NTPApply(ctx context.Context, req NTPApplyRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/ntpApply" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/raise_down.go b/pkg/cloudbroker/extnet/raise_down.go new file mode 100644 index 0000000..fae1b19 --- /dev/null +++ b/pkg/cloudbroker/extnet/raise_down.go @@ -0,0 +1,24 @@ +package extnet + +import ( + "context" + "net/http" + "strconv" +) + +// RaiseDown starting all extnets vnfdevs in "DOWN" tech status +func (e ExtNet) RaiseDown(ctx context.Context) (bool, error) { + url := "/cloudbroker/extnet/raiseDown" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, nil) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/set_default.go b/pkg/cloudbroker/extnet/set_default.go new file mode 100644 index 0000000..48c5378 --- /dev/null +++ b/pkg/cloudbroker/extnet/set_default.go @@ -0,0 +1,45 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for set external network as default +type SetDefaultRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` +} + +func (erq SetDefaultRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// SetDefault sets external network as default for platform +func (e ExtNet) SetDefault(ctx context.Context, req SetDefaultRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/setDefault" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/extnet/update.go b/pkg/cloudbroker/extnet/update.go new file mode 100644 index 0000000..15c712f --- /dev/null +++ b/pkg/cloudbroker/extnet/update.go @@ -0,0 +1,53 @@ +package extnet + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for update external network +type UpdateRequest struct { + // ID of external network + // Required: true + NetID uint64 `url:"net_id"` + + // New external network name + // Required: false + Name string `url:"name,omitempty"` + + // New external network description + // Required: false + Description string `url:"desc,omitempty"` +} + +func (erq UpdateRequest) validate() error { + if erq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// Update updates external network parameters +func (e ExtNet) Update(ctx context.Context, req UpdateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/extnet/update" + + res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/flipgroup.go b/pkg/cloudbroker/flipgroup.go deleted file mode 100644 index a484324..0000000 --- a/pkg/cloudbroker/flipgroup.go +++ /dev/null @@ -1,9 +0,0 @@ -package cloudbroker - -import ( - "github.com/rudecs/decort-sdk/pkg/cloudapi/flipgroup" -) - -func (cb *CloudBroker) FlipGroup() *flipgroup.FlipGroup { - return flipgroup.New(cb.client) -} diff --git a/pkg/cloudbroker/grid.go b/pkg/cloudbroker/grid.go new file mode 100644 index 0000000..739a416 --- /dev/null +++ b/pkg/cloudbroker/grid.go @@ -0,0 +1,8 @@ +package cloudbroker + +import "github.com/rudecs/decort-sdk/pkg/cloudbroker/grid" + +// Accessing the Grid method group +func (cb *CloudBroker) Grid() *grid.Grid { + return grid.New(cb.client) +} diff --git a/pkg/cloudbroker/grid/add.go b/pkg/cloudbroker/grid/add.go new file mode 100644 index 0000000..6921ce1 --- /dev/null +++ b/pkg/cloudbroker/grid/add.go @@ -0,0 +1,59 @@ +package grid + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for location code +type AddRequest struct { + // Grid (platform) ID + // Required: true + GID uint64 `url:"gid"` + + // Name of the location + // Required: true + Name string `url:"name"` + + // Location code typicly used in dns names + // Required: true + LocationCode string `url:"locationcode"` +} + +func (grq AddRequest) validate() error { + if grq.GID == 0 { + return errors.New("validation-error: field GID must be set") + } + if grq.Name == "" { + return errors.New("validation-error: field Name must be set") + } + if grq.LocationCode == "" { + return errors.New("validation-error: field LocationCode must be set") + } + + return nil +} + +// Add location code (e.g. DNS name of this grid) +func (g Grid) Add(ctx context.Context, req AddRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/grid/add" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/grid/change_settings.go b/pkg/cloudbroker/grid/change_settings.go new file mode 100644 index 0000000..42603ae --- /dev/null +++ b/pkg/cloudbroker/grid/change_settings.go @@ -0,0 +1,52 @@ +package grid + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for change grid settings +type ChangeSettingsRequest struct { + // Grid (platform) ID + // Required: true + GID uint64 `url:"id"` + + // Json data of the new settings will override old data + // Required: true + Settings string `url:"settings"` +} + +func (grq ChangeSettingsRequest) validate() error { + if grq.GID == 0 { + return errors.New("validation-error: field GID must be set") + } + if grq.Settings == "" { + return errors.New("validation-error: field Settings must be set") + } + + return nil +} + +// ChangeSettings changes grid settings +func (g Grid) ChangeSettings(ctx context.Context, req ChangeSettingsRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/grid/changeSettings" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/grid/check_vms.go b/pkg/cloudbroker/grid/check_vms.go new file mode 100644 index 0000000..b11767d --- /dev/null +++ b/pkg/cloudbroker/grid/check_vms.go @@ -0,0 +1,45 @@ +package grid + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for check virtual machine +type CheckVMsRequest struct { + // Grid (platform) ID + // Required: true + GID uint64 `url:"gid"` +} + +func (grq CheckVMsRequest) validate() error { + if grq.GID == 0 { + return errors.New("validation-error: field GID must be set") + } + + return nil +} + +// CheckVMs run checkvms jumpscript +func (g Grid) CheckVMs(ctx context.Context, req CheckVMsRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/grid/checkVMs" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/grid/create_system_space.go b/pkg/cloudbroker/grid/create_system_space.go new file mode 100644 index 0000000..6ba9fcd --- /dev/null +++ b/pkg/cloudbroker/grid/create_system_space.go @@ -0,0 +1,79 @@ +package grid + +import ( + "context" + "errors" + "net/http" +) + +// Request struct for create system space +type CreateSystemSpaceRequest struct { + // Grid (platform) ID + // Required: true + GID uint64 `url:"id"` + + // Name of the account/cloudspace to be created for the system + // Required: true + Name string `url:"name"` + + // ID of the specific image + // Required: true + ImageID uint64 `url:"imageId"` + + // Size of base volume + // Required: true + BootSize uint64 `url:"bootsize"` + + // Data disk size in gigabytes + // Required: true + DataDiskSize uint64 `url:"dataDiskSize"` + + // ID of the specific size + // Required: false + SizeID uint64 `url:"sizeId,omitempty"` + + // Number of vcpus to provide + // Required: false + VCPUS uint64 `url:"vcpus,omitempty"` + + // Amount of memory to provide + // Required: false + Memory uint64 `url:"memory,omitempty"` +} + +func (grq CreateSystemSpaceRequest) validate() error { + if grq.GID == 0 { + return errors.New("validation-error: field GID must be set") + } + if grq.Name == "" { + return errors.New("validation-error: field Name must be set") + } + if grq.BootSize == 0 { + return errors.New("validation-error: field BootSize must be set") + } + if grq.ImageID == 0 { + return errors.New("validation-error: field ImageID must be set") + } + if grq.DataDiskSize == 0 { + return errors.New("validation-error: field DataDiskSize must be set") + } + + return nil +} + +// CreateSystemSpace creates system space +func (g Grid) CreateSystemSpace(ctx context.Context, req CreateSystemSpaceRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/grid/createSystemSpace" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + return string(res), nil +} diff --git a/pkg/cloudbroker/grid/execute_maintenance_script.go b/pkg/cloudbroker/grid/execute_maintenance_script.go new file mode 100644 index 0000000..c7aa68f --- /dev/null +++ b/pkg/cloudbroker/grid/execute_maintenance_script.go @@ -0,0 +1,59 @@ +package grid + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for execute script +type ExecuteMaintenanceScriptRequest struct { + // Grid (platform) ID + // Required: true + GID string `url:"gid"` + + // Type of nodes you want to apply the action on + // Required: true + NodesType string `url:"nodestype"` + + // The script you want to run + // Required: true + Script string `url:"script"` +} + +func (grq ExecuteMaintenanceScriptRequest) validate() error { + if grq.GID == "" { + return errors.New("validation-error: field GID must be set") + } + if grq.NodesType == "" { + return errors.New("validation-error: field NodesType must be set") + } + if grq.Script == "" { + return errors.New("validation-error: field Script must be set") + } + + return nil +} + +// ExecuteMaintenanceScript executes maintenance script +func (g Grid) ExecuteMaintenanceScript(ctx context.Context, req ExecuteMaintenanceScriptRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/grid/executeMaintenanceScript" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/grid/get.go b/pkg/cloudbroker/grid/get.go new file mode 100644 index 0000000..e860490 --- /dev/null +++ b/pkg/cloudbroker/grid/get.go @@ -0,0 +1,47 @@ +package grid + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get grid details +type GetRequest struct { + // Grid (platform) ID + // Required: true + GID uint64 `url:"gridId"` +} + +func (grq GetRequest) validate() error { + if grq.GID == 0 { + return errors.New("validation-error: field GID must be set") + } + + return nil +} + +// Get gets information about grid by ID +func (g Grid) Get(ctx context.Context, req GetRequest) (*RecordGrid, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/grid/get" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + info := RecordGrid{} + + err = json.Unmarshal(res, &info) + if err != nil { + return nil, err + } + + return &info, nil +} diff --git a/pkg/cloudbroker/grid/get_backup.go b/pkg/cloudbroker/grid/get_backup.go new file mode 100644 index 0000000..f6d7eaf --- /dev/null +++ b/pkg/cloudbroker/grid/get_backup.go @@ -0,0 +1,56 @@ +package grid + +import ( + "context" + "errors" + "net/http" +) + +// Request struct for get backup +type GetBackupRequest struct { + // Grid (platform) ID + // Required: true + GID uint64 `url:"gid"` +} + +func (grq GetBackupRequest) validate() error { + if grq.GID == 0 { + return errors.New("validation-error: field GID must be set") + } + + return nil +} + +// GetBackup gets platform backup +func (g Grid) GetBackup(ctx context.Context, req GetBackupRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/grid/getBackup" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + return string(res), nil +} + +// GetBackupGET gets platform backup +func (g Grid) GetBackupGET(ctx context.Context, req GetBackupRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/grid/getBackup" + + res, err := g.client.DecortApiCall(ctx, http.MethodGet, url, req) + if err != nil { + return "", err + } + + return string(res), nil +} diff --git a/pkg/cloudbroker/grid/get_diagnosis.go b/pkg/cloudbroker/grid/get_diagnosis.go new file mode 100644 index 0000000..6370295 --- /dev/null +++ b/pkg/cloudbroker/grid/get_diagnosis.go @@ -0,0 +1,56 @@ +package grid + +import ( + "context" + "errors" + "net/http" +) + +// Request struct for get platform snapshot with additional diagnosis +type GetDiagnosisRequest struct { + // Grid (platform) ID + // Required: true + GID uint64 `url:"gid"` +} + +func (grq GetDiagnosisRequest) validate() error { + if grq.GID == 0 { + return errors.New("validation-error: field GID must be set") + } + + return nil +} + +// GetDiagnosis get platform snapshot with additional diagnosis info like a logs, etc +func (g Grid) GetDiagnosis(ctx context.Context, req GetDiagnosisRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/grid/getDiagnosis" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + return string(res), nil +} + +// GetDiagnosisGET get platform snapshot with additional diagnosis info like a logs, etc +func (g Grid) GetDiagnosisGET(ctx context.Context, req GetDiagnosisRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/grid/getDiagnosis" + + res, err := g.client.DecortApiCall(ctx, http.MethodGet, url, req) + if err != nil { + return "", err + } + + return string(res), nil +} diff --git a/pkg/cloudbroker/grid/grid.go b/pkg/cloudbroker/grid/grid.go new file mode 100644 index 0000000..28c521c --- /dev/null +++ b/pkg/cloudbroker/grid/grid.go @@ -0,0 +1,18 @@ +// Operator actions for handling interventions on a grid +package grid + +import ( + "github.com/rudecs/decort-sdk/interfaces" +) + +// Structure for creating request to grid +type Grid struct { + client interfaces.Caller +} + +// Builder for grid endpoints +func New(client interfaces.Caller) *Grid { + return &Grid{ + client: client, + } +} diff --git a/pkg/cloudbroker/grid/list.go b/pkg/cloudbroker/grid/list.go new file mode 100644 index 0000000..a1f7503 --- /dev/null +++ b/pkg/cloudbroker/grid/list.go @@ -0,0 +1,37 @@ +package grid + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get list locations +type ListRequest struct { + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} + +// List gets list all locations +func (g Grid) List(ctx context.Context, req ListRequest) (ListGrids, error) { + url := "/cloudbroker/grid/list" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListGrids{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/grid/list_emails.go b/pkg/cloudbroker/grid/list_emails.go new file mode 100644 index 0000000..8f59ad2 --- /dev/null +++ b/pkg/cloudbroker/grid/list_emails.go @@ -0,0 +1,26 @@ +package grid + +import ( + "context" + "encoding/json" + "net/http" +) + +// ListEmails returns list of email addresses of users +func (g Grid) ListEmails(ctx context.Context) ([]string, error) { + url := "/cloudbroker/grid/listEmails" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, nil) + if err != nil { + return nil, err + } + + list := make([]string, 0) + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/grid/models.go b/pkg/cloudbroker/grid/models.go new file mode 100644 index 0000000..f8c1641 --- /dev/null +++ b/pkg/cloudbroker/grid/models.go @@ -0,0 +1,58 @@ +package grid + +// Resource information +type Resources struct { + // Current resources + Current RecordResource `json:"Current"` + + // Reserved resources + Reserved RecordResource `json:"Reserved"` +} + +// Resource details +type RecordResource struct { + // Number of CPU + CPU uint64 `json:"cpu"` + + // Disk size + DiskSize uint64 `json:"disksize"` + + // External IPs + ExtIPs uint64 `json:"extips"` + + // External traffic + ExtTraffic uint64 `json:"exttraffic"` + + // Number of GPU + GPU uint64 `json:"gpu"` + + // Number of RAM + RAM uint64 `json:"ram"` +} + +// Detailed information about grid +type RecordGrid struct { + // Resource information + Resources Resources `json:"Resources"` + + // Flag + Flag string `json:"flag"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Location code + LocationCode string `json:"locationCode"` + + // Name + Name string `json:"name"` +} + +// List Grids +type ListGrids []RecordGrid diff --git a/pkg/cloudbroker/grid/purge_logs.go b/pkg/cloudbroker/grid/purge_logs.go new file mode 100644 index 0000000..fad8859 --- /dev/null +++ b/pkg/cloudbroker/grid/purge_logs.go @@ -0,0 +1,53 @@ +package grid + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for purge logs +type PurgeLogsRequest struct { + // Grid (platform) ID + // Required: true + GID uint64 `url:"gid"` + + // Age of the records to remove, e.g. -1h for records older than 1 hour, -1w - one week, etc + // Required: true + Age string `url:"age"` +} + +func (grq PurgeLogsRequest) validate() error { + if grq.GID == 0 { + return errors.New("validation-error: field GID must be set") + } + if grq.Age == "" { + return errors.New("validation-error: field Age must be set") + } + + return nil +} + +// PurgeLogs clear Log and ECO records that are older than the specified age. +// By default, records older than one week are removed +func (g Grid) PurgeLogs(ctx context.Context, req PurgeLogsRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/grid/purgeLogs" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/grid/rename.go b/pkg/cloudbroker/grid/rename.go new file mode 100644 index 0000000..0f038c6 --- /dev/null +++ b/pkg/cloudbroker/grid/rename.go @@ -0,0 +1,52 @@ +package grid + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for rename grid +type RenameRequest struct { + // Grid (platform) ID + // Required: true + GID uint64 `url:"gid"` + + // New name + // Required: true + Name string `url:"Name"` +} + +func (grq RenameRequest) validate() error { + if grq.GID == 0 { + return errors.New("validation-error: field GID must be set") + } + if grq.Name == "" { + return errors.New("validation-error: field Name must be set") + } + + return nil +} + +// Rename renames a grid +func (g Grid) Rename(ctx context.Context, req RenameRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/grid/rename" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/grid/services_restart.go b/pkg/cloudbroker/grid/services_restart.go new file mode 100644 index 0000000..863f60b --- /dev/null +++ b/pkg/cloudbroker/grid/services_restart.go @@ -0,0 +1,52 @@ +package grid + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for restart services +type ServicesRestartRequest struct { + // Grid (platform) ID + // Required: true + GID uint64 `url:"gid"` + + // Node ID + // Required: true + NID uint64 `url:"nid"` +} + +func (grq ServicesRestartRequest) validate() error { + if grq.GID == 0 { + return errors.New("validation-error: field GID must be set") + } + if grq.NID == 0 { + return errors.New("validation-error: field NID must be set") + } + + return nil +} + +// ServicesRestart restarts decort services on the node +func (g Grid) ServicesRestart(ctx context.Context, req ServicesRestartRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/grid/servicesRestart" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/grid/set_cpu_allocation_ratio.go b/pkg/cloudbroker/grid/set_cpu_allocation_ratio.go new file mode 100644 index 0000000..84fa5fb --- /dev/null +++ b/pkg/cloudbroker/grid/set_cpu_allocation_ratio.go @@ -0,0 +1,52 @@ +package grid + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for set allocation +type SetCPUAllocationRatioRequest struct { + // Grid (platform) ID + // Required: true + GID uint64 `url:"gridId"` + + // Allocation ratio + // Required: true + Ratio float64 `url:"ratio"` +} + +func (grq SetCPUAllocationRatioRequest) validate() error { + if grq.GID == 0 { + return errors.New("validation-error: field GID must be set") + } + if grq.Ratio == 0.0 { + return errors.New("validation-error: field Ratio must be set") + } + + return nil +} + +// SetCPUAllocationRatio sets CPU allocation ratio +func (g Grid) SetCPUAllocationRatio(ctx context.Context, req SetCPUAllocationRatioRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/grid/setCpuAllocationRatio" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/grid/set_mem_allocation_ratio.go b/pkg/cloudbroker/grid/set_mem_allocation_ratio.go new file mode 100644 index 0000000..a9a22b8 --- /dev/null +++ b/pkg/cloudbroker/grid/set_mem_allocation_ratio.go @@ -0,0 +1,52 @@ +package grid + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for set memory allocation +type SetMemAllocationRatioRequest struct { + // Grid (platform) ID + // Required: true + GID uint64 `url:"gridId"` + + // Allocation ratio + // Required: true + Ratio float64 `url:"ratio"` +} + +func (grq SetMemAllocationRatioRequest) validate() error { + if grq.GID == 0 { + return errors.New("validation-error: field GID must be set") + } + if grq.Ratio == 0.0 { + return errors.New("validation-error: field Ratio must be set") + } + + return nil +} + +// SetMemAllocationRatio sets memory allocation ratio +func (g Grid) SetMemAllocationRatio(ctx context.Context, req SetMemAllocationRatioRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/grid/setMemAllocationRatio" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/grid/status.go b/pkg/cloudbroker/grid/status.go new file mode 100644 index 0000000..deea0fb --- /dev/null +++ b/pkg/cloudbroker/grid/status.go @@ -0,0 +1,41 @@ +package grid + +import ( + "context" + "net/http" + "strconv" +) + +// Status check if current environment is active +func (g Grid) Status(ctx context.Context) (bool, error) { + url := "/cloudbroker/grid/status" + + res, err := g.client.DecortApiCall(ctx, http.MethodPost, url, nil) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} + +// StatusGET check if current environment is active +func (g Grid) StatusGET(ctx context.Context) (bool, error) { + url := "/cloudbroker/grid/status" + + res, err := g.client.DecortApiCall(ctx, http.MethodGet, url, nil) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/image.go b/pkg/cloudbroker/image.go index 56cb856..050b4ad 100644 --- a/pkg/cloudbroker/image.go +++ b/pkg/cloudbroker/image.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudbroker/image" ) +// Accessing the Image method group func (cb *CloudBroker) Image() *image.Image { return image.New(cb.client) } diff --git a/pkg/cloudbroker/image/computeci_set.go b/pkg/cloudbroker/image/computeci_set.go index 489150d..957cd44 100644 --- a/pkg/cloudbroker/image/computeci_set.go +++ b/pkg/cloudbroker/image/computeci_set.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for set compute CI type ComputeCISetRequest struct { - ImageID uint64 `url:"imageId"` + // ID of the image + // Required: true + ImageID uint64 `url:"imageId"` + + // ID of the compute CI + // Required: true ComputeCIID uint64 `url:"computeciId"` } -func (irq ComputeCISetRequest) Validate() error { +func (irq ComputeCISetRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID must be set") } @@ -23,8 +29,9 @@ func (irq ComputeCISetRequest) Validate() error { return nil } +// ComputeCISet set compute CI ID for image func (i Image) ComputeCISet(ctx context.Context, req ComputeCISetRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/image/computeci_unset.go b/pkg/cloudbroker/image/computeci_unset.go index 7fb85ef..d0f2b53 100644 --- a/pkg/cloudbroker/image/computeci_unset.go +++ b/pkg/cloudbroker/image/computeci_unset.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for unset compute CI type ComputeCIUnsetRequest struct { + // ID of the image + // Required: true ImageID uint64 `url:"imageId"` } -func (irq ComputeCIUnsetRequest) Validate() error { +func (irq ComputeCIUnsetRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID must be set") } @@ -19,8 +22,9 @@ func (irq ComputeCIUnsetRequest) Validate() error { return nil } +// ComputeCIUnset unset compute CI ID from image func (i Image) ComputeCIUnset(ctx context.Context, req ComputeCIUnsetRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/image/create_cdrom_image.go b/pkg/cloudbroker/image/create_cdrom_image.go index e44efb7..415fe56 100644 --- a/pkg/cloudbroker/image/create_cdrom_image.go +++ b/pkg/cloudbroker/image/create_cdrom_image.go @@ -3,25 +3,60 @@ package image import ( "context" "errors" - "github.com/rudecs/decort-sdk/internal/validators" "net/http" "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for create CD-ROM image type CreateCDROMImageRequest struct { - Name string `url:"name"` - URL string `url:"url"` - GID uint64 `url:"gid"` - AccountID uint64 `url:"accountId,omitempty"` - SepID uint64 `url:"sep_id,omitempty"` - PoolName string `url:"pool_name,omitempty"` - UsernameDL string `url:"usernameDL,omitempty"` - PasswordDl string `url:"passwordDL,omitempty"` - Architecture string `url:"architecture,omitempty"` - Drivers []string `url:"drivers"` + // Name of the rescue disk + // Required: true + Name string `url:"name"` + + // URL where to download ISO from + // Required: true + URL string `url:"url"` + + // Grid (platform) ID where this CD-ROM image should be create in + // Required: true + GID uint64 `url:"gid"` + + // Account ID to make the image exclusive + // Required: false + AccountID uint64 `url:"accountId,omitempty"` + + // Storage endpoint provider ID for place rescue CD + // Required: false + SEPID uint64 `url:"sep_id,omitempty"` + + // Pool for place rescue CD + // Required: false + PoolName string `url:"pool_name,omitempty"` + + // Username for remote media download + // Required: false + UsernameDL string `url:"usernameDL,omitempty"` + + // Password for remote media download + // Required: false + PasswordDl string `url:"passwordDL,omitempty"` + + // Binary architecture of this image + // Should be one of: + // - X86_64 + // - PPC64_LE + // Required: false + Architecture string `url:"architecture,omitempty"` + + // List of types of compute suitable for image. + // Example: [ "KVM_X86" ] + // Required: true + Drivers []string `url:"drivers"` } -func (irq CreateCDROMImageRequest) Validate() error { +func (irq CreateCDROMImageRequest) validate() error { if irq.Name == "" { return errors.New("validation-error: field Name must be set") } @@ -31,11 +66,9 @@ func (irq CreateCDROMImageRequest) Validate() error { if irq.GID == 0 { return errors.New("validation-error: field GID must be set") } - if len(irq.Drivers) == 0 || len(irq.Drivers) > 1 { return errors.New("validation-error: field Drivers can not be empty or have 2 or more elements") } - for _, v := range irq.Drivers { validate := validators.StringInSlice(v, []string{"KVM_X86"}) if !validate { @@ -46,8 +79,9 @@ func (irq CreateCDROMImageRequest) Validate() error { return nil } +// CreateCDROMImage creates CD-ROM image from an ISO identified by URL func (i Image) CreateCDROMImage(ctx context.Context, req CreateCDROMImageRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } diff --git a/pkg/cloudbroker/image/create_image.go b/pkg/cloudbroker/image/create_image.go index f8375ef..af3d413 100644 --- a/pkg/cloudbroker/image/create_image.go +++ b/pkg/cloudbroker/image/create_image.go @@ -3,31 +3,91 @@ package image import ( "context" "errors" - "github.com/rudecs/decort-sdk/internal/validators" "net/http" "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for create image type CreateRequest struct { - Name string `url:"name"` - URL string `url:"url"` - GID uint64 `url:"gid"` - BootType string `url:"boottype"` - ImageType string `url:"imagetype"` - HotResize bool `url:"hotresize,omitempty"` - Username string `url:"username,omitempty"` - Password string `url:"password,omitempty"` - AccountID uint64 `url:"accountId,omitempty"` - UsernameDL string `url:"usernameDL,omitempty"` - PasswordDL string `url:"passwordDL,omitempty"` - SepID uint64 `url:"sepId,omitempty"` - PoolName string `url:"poolName,omitempty"` - Architecture string `url:"architecture,omitempty"` - Drivers []string `url:"drivers,omitempty"` - Bootable bool `url:"bootable,omitempty"` + // Name of the rescue disk + // Required: true + Name string `url:"name"` + + // URL where to download media from + // Required: true + URL string `url:"url"` + + // Grid (platform) ID where this template should be create in + // Required: true + GID uint64 `url:"gid"` + + // Boot type of image + // Should be one of: + // - bios + // - UEFI + // Required: true + BootType string `url:"boottype"` + + // Image type + // Should be one of: + // - linux + // - windows + // - or other + // Required: true + ImageType string `url:"imagetype"` + + // Does this machine supports hot resize + // Required: false + HotResize bool `url:"hotresize,omitempty"` + + // Optional username for the image + // Required: false + Username string `url:"username,omitempty"` + + // Optional password for the image + // Required: false + Password string `url:"password,omitempty"` + + // Account ID to make the image exclusive + // Required: false + AccountID uint64 `url:"accountId,omitempty"` + + // Username for upload binary media + // Required: false + UsernameDL string `url:"usernameDL,omitempty"` + + // Password for upload binary media + // Required: false + PasswordDL string `url:"passwordDL,omitempty"` + + // Storage endpoint provider ID + // Required: false + SEPID uint64 `url:"sepId,omitempty"` + + // Pool for image create + // Required: false + PoolName string `url:"poolName,omitempty"` + + // Binary architecture of this image + // Should be one of: + // - X86_64 + // - PPC64_LE + // Required: false + Architecture string `url:"architecture,omitempty"` + + // List of types of compute suitable for image + // Example: [ "KVM_X86" ] + // Required: true + Drivers []string `url:"drivers"` + + // Bootable image or not + // Required: false + Bootable bool `url:"bootable,omitempty"` } -func (irq CreateRequest) Validate() error { +func (irq CreateRequest) validate() error { if irq.Name == "" { return errors.New("validation-error: field Name must be set") } @@ -43,7 +103,6 @@ func (irq CreateRequest) Validate() error { if irq.ImageType == "" { return errors.New("validation-error: field ImageType must be set") } - validate := validators.StringInSlice(irq.BootType, []string{"bios", "uefi"}) if !validate { return errors.New("validation-error: field BootType can be bios or uefi") @@ -56,8 +115,9 @@ func (irq CreateRequest) Validate() error { return nil } +// CreateImage creates image from a media identified by URL func (i Image) CreateImage(ctx context.Context, req CreateRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } diff --git a/pkg/cloudbroker/image/create_virtual.go b/pkg/cloudbroker/image/create_virtual.go index 48cb3ad..7a0a76f 100644 --- a/pkg/cloudbroker/image/create_virtual.go +++ b/pkg/cloudbroker/image/create_virtual.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for create virtual image type CreateVirtualRequest struct { - Name string `url:"name"` + // Name of the virtual image to create + // Required: true + Name string `url:"name"` + + // ID of real image to link this virtual image to upon creation + // Required: true TargetID uint64 `url:"targetId"` } -func (irq CreateVirtualRequest) Validate() error { +func (irq CreateVirtualRequest) validate() error { if irq.Name == "" { return errors.New("validation-error: field Name must be set") } @@ -23,8 +29,9 @@ func (irq CreateVirtualRequest) Validate() error { return nil } +// CreateVirtual creates virtual image func (i Image) CreateVirtual(ctx context.Context, req CreateVirtualRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } diff --git a/pkg/cloudbroker/image/delete.go b/pkg/cloudbroker/image/delete.go index 5117cc2..e53787e 100644 --- a/pkg/cloudbroker/image/delete.go +++ b/pkg/cloudbroker/image/delete.go @@ -7,13 +7,22 @@ import ( "strconv" ) +// Request struct for delete image type DeleteRequest struct { - ImageID uint64 `url:"imageId"` - Reason string `url:"reason"` - Permanently bool `url:"permanently,omitempty"` + // ID of the image to delete + // Required: true + ImageID uint64 `url:"imageId"` + + // Reason for action + // Required: true + Reason string `url:"reason"` + + // Whether to completely delete the image + // Required: false + Permanently bool `url:"permanently,omitempty"` } -func (irq DeleteRequest) Validate() error { +func (irq DeleteRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID must be set") } @@ -24,8 +33,9 @@ func (irq DeleteRequest) Validate() error { return nil } +// Delete deletes image by ID func (i Image) Delete(ctx context.Context, req DeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/image/delete_cdrom_image.go b/pkg/cloudbroker/image/delete_cdrom_image.go index e408ac7..5b638c5 100644 --- a/pkg/cloudbroker/image/delete_cdrom_image.go +++ b/pkg/cloudbroker/image/delete_cdrom_image.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for delete CD-ROM image type DeleteCDROMImageRequest struct { - ImageID uint64 `url:"imageId"` - Permanently bool `url:"permanently"` + // ID of the CD-ROM image to delete + // Required: true + ImageID uint64 `url:"imageId"` + + // Whether to completely delete the CD-ROM image, needs to be unused + // Required: true + Permanently bool `url:"permanently"` } -func (irq DeleteCDROMImageRequest) Validate() error { +func (irq DeleteCDROMImageRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID must be set") } @@ -20,8 +26,9 @@ func (irq DeleteCDROMImageRequest) Validate() error { return nil } +// DeleteCDROMImage delete a CD-ROM image func (i Image) DeleteCDROMImage(ctx context.Context, req DeleteCDROMImageRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/image/delete_images.go b/pkg/cloudbroker/image/delete_images.go index c874af1..0eb8e9d 100644 --- a/pkg/cloudbroker/image/delete_images.go +++ b/pkg/cloudbroker/image/delete_images.go @@ -7,25 +7,32 @@ import ( "strconv" ) +// Request struct for delete images type DeleteImagesRequest struct { - ImageIDs []uint64 `url:"imageIds"` - Reason string `url:"reason"` - Permanently bool `url:"permanently"` + // List of images to be deleted + // Required: true + ImageIDs []uint64 `url:"imageIds"` + + // Reason for action + // Required: true + Reason string `url:"reason,omitempty"` + + // Whether to completely delete the images + // Required: true + Permanently bool `url:"permanently,omitempty"` } -func (irq DeleteImagesRequest) Validate() error { +func (irq DeleteImagesRequest) validate() error { if len(irq.ImageIDs) == 0 { return errors.New("validation-error: field ImageIDs must be set") } - if irq.Reason == "" { - return errors.New("validation-error: field Reason must be set") - } return nil } +// DeleteImages deletes images func (i Image) DeleteImages(ctx context.Context, req DeleteImagesRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/image/disable.go b/pkg/cloudbroker/image/disable.go index 3d4d554..e933476 100644 --- a/pkg/cloudbroker/image/disable.go +++ b/pkg/cloudbroker/image/disable.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for disable image type DisableRequest struct { + // ID of image to be disabled + // Required: true ImageID uint64 `url:"imageId"` } -func (irq DisableRequest) Validate() error { +func (irq DisableRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID must be set") } @@ -19,8 +22,9 @@ func (irq DisableRequest) Validate() error { return nil } +// Disable disables image func (i Image) Disable(ctx context.Context, req DisableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/image/edit.go b/pkg/cloudbroker/image/edit.go index 98d6db0..d0c3ae9 100644 --- a/pkg/cloudbroker/image/edit.go +++ b/pkg/cloudbroker/image/edit.go @@ -7,17 +7,38 @@ import ( "strconv" ) +// Request struct for edit image type EditRequest struct { - ImageID uint64 `url:"imageId"` - Name string `url:"name,omitempty"` - Username string `url:"username,omitempty"` - Password string `url:"password,omitempty"` + // ID of the image to edit + // Required: true + ImageID uint64 `url:"imageId"` + + // Name for the image + // Required: false + Name string `url:"name,omitempty"` + + // Username for the image + // Required: false + Username string `url:"username,omitempty"` + + // Password for the image + // Required: false + Password string `url:"password,omitempty"` + + // Account ID to make the image exclusive + // Required: false AccountID uint64 `url:"accountId,omitempty"` - HotResize bool `url:"hotresize,omitempty"` - Bootable bool `url:"bootable,omitempty"` + + // Does this machine supports hot resize + // Required: false + HotResize bool `url:"hotresize,omitempty"` + + // Does this image boot OS + // Required: false + Bootable bool `url:"bootable,omitempty"` } -func (irq EditRequest) Validate() error { +func (irq EditRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID must be set") } @@ -25,8 +46,9 @@ func (irq EditRequest) Validate() error { return nil } +// Edit edits an existing image func (i Image) Edit(ctx context.Context, req EditRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/image/enable.go b/pkg/cloudbroker/image/enable.go index 5f40897..e316afb 100644 --- a/pkg/cloudbroker/image/enable.go +++ b/pkg/cloudbroker/image/enable.go @@ -7,11 +7,14 @@ import ( "strconv" ) +// Request struct for enable image type EnableRequest struct { + // ID of image to be enabled + // Required: true ImageID uint64 `url:"imageId"` } -func (irq EnableRequest) Validate() error { +func (irq EnableRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID must br set") } @@ -19,8 +22,9 @@ func (irq EnableRequest) Validate() error { return nil } +// Enable enables image func (i Image) Enable(ctx context.Context, req EnableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -38,4 +42,4 @@ func (i Image) Enable(ctx context.Context, req EnableRequest) (bool, error) { } return result, nil -} \ No newline at end of file +} diff --git a/pkg/cloudbroker/image/get.go b/pkg/cloudbroker/image/get.go index 08eec36..3f3c477 100644 --- a/pkg/cloudbroker/image/get.go +++ b/pkg/cloudbroker/image/get.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get image details type GetRequest struct { + // ID of image + // Required: true ImageID uint64 `url:"imageId"` } -func (irq GetRequest) Validate() error { +func (irq GetRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID must be set") } @@ -19,25 +22,26 @@ func (irq GetRequest) Validate() error { return nil } -func (i Image) Get(ctx context.Context, req GetRequest) (*ImageRecord, error) { - err := req.Validate() +// Get get image details by ID +func (i Image) Get(ctx context.Context, req GetRequest) (*RecordImage, error) { + err := req.validate() if err != nil { return nil, err } url := "/cloudbroker/image/get" - result := ImageRecord{} + info := RecordImage{} res, err := i.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - err = json.Unmarshal(res, &result) + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return &result, nil + return &info, nil } diff --git a/pkg/cloudbroker/image/image.go b/pkg/cloudbroker/image/image.go index bb34ee9..ec90d64 100644 --- a/pkg/cloudbroker/image/image.go +++ b/pkg/cloudbroker/image/image.go @@ -1,11 +1,14 @@ +// Lists all the images. A image is a template which can be used to deploy machines package image import "github.com/rudecs/decort-sdk/interfaces" +// Structure for creating request to image type Image struct { client interfaces.Caller } +// Builder for image endpoint func New(client interfaces.Caller) *Image { return &Image{ client: client, diff --git a/pkg/cloudbroker/image/link.go b/pkg/cloudbroker/image/link.go index c08c33b..ee6a2d7 100644 --- a/pkg/cloudbroker/image/link.go +++ b/pkg/cloudbroker/image/link.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for link virtual image to another image type LinkRequest struct { - ImageID uint64 `url:"imageId"` + // ID of the virtual image + // Required: true + ImageID uint64 `url:"imageId"` + + // ID of real image to link this virtual image to + // Required: true TargetID uint64 `url:"targetId"` } -func (irq LinkRequest) Validate() error { +func (irq LinkRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID must be set") } @@ -23,8 +29,9 @@ func (irq LinkRequest) Validate() error { return nil } +// Link links virtual image to another image in the platform func (i Image) Link(ctx context.Context, req LinkRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -42,4 +49,4 @@ func (i Image) Link(ctx context.Context, req LinkRequest) (bool, error) { } return result, nil -} \ No newline at end of file +} diff --git a/pkg/cloudbroker/image/list.go b/pkg/cloudbroker/image/list.go index ada25c4..6b83a81 100644 --- a/pkg/cloudbroker/image/list.go +++ b/pkg/cloudbroker/image/list.go @@ -6,13 +6,26 @@ import ( "net/http" ) +// Request struct for get list available images type ListRequest struct { - SepID uint64 `url:"sepId,omitempty"` + // Filter images by storage endpoint provider ID + // Required: false + SepID uint64 `url:"sepId,omitempty"` + + // Filter images by account ID availability + // Required: false SharedWith uint64 `url:"sharedWith,omitempty"` - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } +// List gets list of information about images func (i Image) List(ctx context.Context, req ListRequest) (ListImages, error) { url := "/cloudbroker/image/list" diff --git a/pkg/cloudbroker/image/list_stacks.go b/pkg/cloudbroker/image/list_stacks.go index c872209..fdc120e 100644 --- a/pkg/cloudbroker/image/list_stacks.go +++ b/pkg/cloudbroker/image/list_stacks.go @@ -7,13 +7,22 @@ import ( "net/http" ) +// Request struct for get list stack type ListStacksRequest struct { + // Image ID + // Required: true ImageID uint64 `url:"imageId"` - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (irq ListStacksRequest) Validate() error { +func (irq ListStacksRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID must be set") } @@ -21,8 +30,9 @@ func (irq ListStacksRequest) Validate() error { return nil } +// ListStacks gets list stack by image ID func (i Image) ListStacks(ctx context.Context, req ListStacksRequest) (ListStacks, error) { - err := req.Validate() + err := req.validate() if err != nil { return nil, err } diff --git a/pkg/cloudbroker/image/models.go b/pkg/cloudbroker/image/models.go index 1b78d8f..d85c742 100644 --- a/pkg/cloudbroker/image/models.go +++ b/pkg/cloudbroker/image/models.go @@ -1,82 +1,226 @@ package image -type ImageRecord struct { - UNCPath string `json:"UNCPath"` - CKey string `json:"_ckey"` - Meta []interface{} `json:"_meta"` - AccountID uint64 `json:"accountId"` - ACL []ACL `json:"acl"` - Architecture string `json:"architecture"` - BootType string `json:"bootType"` - Bootable bool `json:"bootable"` - ComputeCIID uint64 `json:"computeciId"` - DeletedTime uint64 `json:"deletedTime"` - Desc string `json:"desc"` - Drivers []string `json:"drivers"` - Enabled bool `json:"enabled"` - Gid uint64 `json:"gid"` - GUID uint64 `json:"guid"` - History []History `json:"history"` - HotResize bool `json:"hotResize"` - ID uint64 `json:"id"` - LastModified uint64 `json:"lastModified"` - LinkTo uint64 `json:"linkTo"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - Password string `json:"password"` - Pool string `json:"pool"` - ProviderName string `json:"provider_name"` - PurgeAttempts uint64 `json:"purgeAttempts"` - ReferenceID string `json:"referenceId"` - ResID string `json:"resId"` - ResName string `json:"resName"` - RescueCD bool `json:"rescuecd"` - SepID uint64 `json:"sepId"` - SharedWith []uint64 `json:"sharedWith"` - Size uint64 `json:"size"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - Type string `json:"type"` - URL string `json:"url"` - Username string `json:"username"` - Version string `json:"version"` - Virtual bool `json:"virtual"` +// Detailed information about image +type RecordImage struct { + // UNC path + UNCPath string `json:"UNCPath"` + + // CKey + CKey string `json:"_ckey"` + + // Meta + Meta []interface{} `json:"_meta"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Access Control List + ACL ListACL `json:"acl"` + + // Architecture + Architecture string `json:"architecture"` + + // Boot type + BootType string `json:"bootType"` + + // Bootable + Bootable bool `json:"bootable"` + + // Compute CI ID + ComputeCIID uint64 `json:"computeciId"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // Drivers + Drivers []string `json:"drivers"` + + // Enabled + Enabled bool `json:"enabled"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // List history + History ListHistory `json:"history"` + + // Hot resize + HotResize bool `json:"hotResize"` + + // ID + ID uint64 `json:"id"` + + // Last modified + LastModified uint64 `json:"lastModified"` + + // Link to + LinkTo uint64 `json:"linkTo"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Password + Password string `json:"password"` + + // Pool + Pool string `json:"pool"` + + // Provider name + ProviderName string `json:"provider_name"` + + // Purge attempts + PurgeAttempts uint64 `json:"purgeAttempts"` + + // Reference ID + ReferenceID string `json:"referenceId"` + + // Resource ID + ResID string `json:"resId"` + + // Resource name + ResName string `json:"resName"` + + // Rescue CD + RescueCD bool `json:"rescuecd"` + + // SEP ID + SEPID uint64 `json:"sepId"` + + // List shared with + SharedWith []uint64 `json:"sharedWith"` + + // Size + Size uint64 `json:"size"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Type + Type string `json:"type"` + + // URL + URL string `json:"url"` + + // Username + Username string `json:"username"` + + // Version + Version string `json:"version"` + + // Virtual + Virtual bool `json:"virtual"` } -type ListImages []ImageRecord +// List images +type ListImages []RecordImage +// Access Control List type ACL struct { - Explicit bool `json:"explicit"` - GUID string `json:"guid"` - Right string `json:"right"` - Status string `json:"status"` - Type string `json:"type"` + // Explicit + Explicit bool `json:"explicit"` + + // GUID + GUID string `json:"guid"` + + // Right + Right string `json:"right"` + + // Status + Status string `json:"status"` + + // Type + Type string `json:"type"` + + // User group ID UserGroupID string `json:"userGroupId"` } + +// List ACL +type ListACL []ACL + +// History information type History struct { - GUID string `json:"guid"` - ID uint64 `json:"id"` + // GUID + GUID string `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Timestamp Timestamp uint64 `json:"timestamp"` } +// List history +type ListHistory []History + +// List stacks type ListStacks []struct { - CKey string `json:"_ckey"` - Meta []interface{} `json:"_meta"` - APIURL string `json:"apiUrl"` - APIKey string `json:"apikey"` - AppID string `json:"appId"` - Desc string `json:"desc"` - Drivers []string `json:"drivers"` - Eco interface{} `json:"eco"` - Error uint64 `json:"error"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - Images []uint64 `json:"images"` - Login string `json:"login"` - Name string `json:"name"` - Passwd string `json:"passwd"` - ReferenceID string `json:"referenceId"` - Status string `json:"status"` - Type string `json:"type"` + // CKey + CKey string `json:"_ckey"` + + // Meta + Meta []interface{} `json:"_meta"` + + // API URL + APIURL string `json:"apiUrl"` + + // API key + APIKey string `json:"apikey"` + + // App ID + AppID string `json:"appId"` + + // Description + Description string `json:"desc"` + + // Drivers + Drivers []string `json:"drivers"` + + // Eco + Eco interface{} `json:"eco"` + + // Error + Error uint64 `json:"error"` + + // Grid ID + GID uint64 `json:"gid"` + + // GID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // List image IDs + Images []uint64 `json:"images"` + + // Login + Login string `json:"login"` + + // Name + Name string `json:"name"` + + // Password + Password string `json:"passwd"` + + // Reference ID + ReferenceID string `json:"referenceId"` + + // Status + Status string `json:"status"` + + // Type + Type string `json:"type"` } diff --git a/pkg/cloudbroker/image/rename.go b/pkg/cloudbroker/image/rename.go index e1b42e7..2d6e790 100644 --- a/pkg/cloudbroker/image/rename.go +++ b/pkg/cloudbroker/image/rename.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for rename image type RenameRequest struct { + // ID of the virtual image to rename + // Required: true ImageID uint64 `url:"imageId"` - Name string `url:"name"` + + // New name + // Required: true + Name string `url:"name"` } -func (irq RenameRequest) Validate() error { +func (irq RenameRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID must be set") } @@ -23,8 +29,9 @@ func (irq RenameRequest) Validate() error { return nil } +// Rename renames image by ID func (i Image) Rename(ctx context.Context, req RenameRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -42,4 +49,4 @@ func (i Image) Rename(ctx context.Context, req RenameRequest) (bool, error) { } return result, nil -} \ No newline at end of file +} diff --git a/pkg/cloudbroker/image/share.go b/pkg/cloudbroker/image/share.go index ff0e54a..2fe20d6 100644 --- a/pkg/cloudbroker/image/share.go +++ b/pkg/cloudbroker/image/share.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for share image type ShareRequest struct { - ImageId uint64 `url:"imageId"` + // ID of the image to share + // Required: true + ImageId uint64 `url:"imageId"` + + // List of account IDs + // Required: true AccountIDs []uint64 `url:"accounts"` } -func (irq ShareRequest) Validate() error { +func (irq ShareRequest) validate() error { if irq.ImageId == 0 { return errors.New("validation-error: field ImageID must be set") } @@ -23,8 +29,9 @@ func (irq ShareRequest) Validate() error { return nil } +// Share shares image with accounts func (i Image) Share(ctx context.Context, req ShareRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/image/sync_create_image.go b/pkg/cloudbroker/image/sync_create_image.go index f55fe83..4a5b34c 100644 --- a/pkg/cloudbroker/image/sync_create_image.go +++ b/pkg/cloudbroker/image/sync_create_image.go @@ -3,31 +3,91 @@ package image import ( "context" "errors" - "github.com/rudecs/decort-sdk/internal/validators" "net/http" "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for sync create image type SyncCreateRequest struct { - Name string `url:"name"` - URL string `url:"url"` - GID uint64 `url:"gid"` - BootType string `url:"boottype"` - ImageType string `url:"imagetype"` - HotResize bool `url:"hotresize,omitempty"` - Username string `url:"username,omitempty"` - Password string `url:"password,omitempty"` - AccountID uint64 `url:"accountId,omitempty"` - UsernameDL string `url:"usernameDL,omitempty"` - PasswordDL string `url:"passwordDL,omitempty"` - SepID uint64 `url:"sepId,omitempty"` - PoolName string `url:"poolName,omitempty"` - Architecture string `url:"architecture,omitempty"` - Drivers []string `url:"drivers"` - Bootable bool `url:"bootable,omitempty"` + // Name of the rescue disk + // Required: true + Name string `url:"name"` + + // URL where to download media from + // Required: true + URL string `url:"url"` + + // Grid (platform) ID where this template should be create in + // Required: true + GID uint64 `url:"gid"` + + // Boot type of image + // Should be one of: + // - bios + // - UEFI + // Required: true + BootType string `url:"boottype"` + + // Image type + // Should be one of: + // - linux + // - windows + // - or other + // Required: true + ImageType string `url:"imagetype"` + + // Does this machine supports hot resize + // Required: false + HotResize bool `url:"hotresize,omitempty"` + + // Optional username for the image + // Required: false + Username string `url:"username,omitempty"` + + // Optional password for the image + // Required: false + Password string `url:"password,omitempty"` + + // Account ID to make the image exclusive + // Required: false + AccountID uint64 `url:"accountId,omitempty"` + + // Username for upload binary media + // Required: false + UsernameDL string `url:"usernameDL,omitempty"` + + // Password for upload binary media + // Required: false + PasswordDL string `url:"passwordDL,omitempty"` + + // Storage endpoint provider ID + // Required: false + SEPID uint64 `url:"sepId,omitempty"` + + // Pool for image create + // Required: false + PoolName string `url:"poolName,omitempty"` + + // Binary architecture of this image + // Should be one of: + // - X86_64 + // - PPC64_LE + // Required: false + Architecture string `url:"architecture,omitempty"` + + // List of types of compute suitable for image + // Example: [ "KVM_X86" ] + // Required: true + Drivers []string `url:"drivers"` + + // Bootable image or not + // Required: false + Bootable bool `url:"bootable,omitempty"` } -func (irq SyncCreateRequest) Validate() error { +func (irq SyncCreateRequest) validate() error { if irq.Name == "" { return errors.New("validation-error: field Name must be set") } @@ -43,7 +103,6 @@ func (irq SyncCreateRequest) Validate() error { if irq.ImageType == "" { return errors.New("validation-error: field ImageType must be set") } - validate := validators.StringInSlice(irq.BootType, []string{"bios", "uefi"}) if !validate { return errors.New("validation-error: field BootType can be bios or uefi") @@ -52,11 +111,9 @@ func (irq SyncCreateRequest) Validate() error { if !validate { return errors.New("validation-error: field ImageType can be windows, linux or other") } - if len(irq.Drivers) == 0 || len(irq.Drivers) > 1 { return errors.New("validation-error: field Drivers can not be empty or have 2 or more elements") } - for _, v := range irq.Drivers { validate := validators.StringInSlice(v, []string{"KVM_X86"}) if !validate { @@ -67,8 +124,9 @@ func (irq SyncCreateRequest) Validate() error { return nil } +// SyncCreate creates image from a media identified by URL (in synchronous mode) func (i Image) SyncCreate(ctx context.Context, req SyncCreateRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } @@ -86,4 +144,4 @@ func (i Image) SyncCreate(ctx context.Context, req SyncCreateRequest) (uint64, e } return result, nil -} \ No newline at end of file +} diff --git a/pkg/cloudbroker/image/update_nodes.go b/pkg/cloudbroker/image/update_nodes.go index 9095ddb..4785c40 100644 --- a/pkg/cloudbroker/image/update_nodes.go +++ b/pkg/cloudbroker/image/update_nodes.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for update nodes type UpdateNodesRequest struct { - ImageID uint64 `url:"imageId"` + // Image ID + // Required: true + ImageID uint64 `url:"imageId"` + + // List of stacks + // Required: false EnabledStacks []uint64 `url:"enabledStacks,omitempty"` } -func (irq UpdateNodesRequest) Validate() error { +func (irq UpdateNodesRequest) validate() error { if irq.ImageID == 0 { return errors.New("validation-error: field ImageID must be set") } @@ -20,8 +26,9 @@ func (irq UpdateNodesRequest) Validate() error { return nil } +// UpdateNodes udates image availability on nodes func (i Image) UpdateNodes(ctx context.Context, req UpdateNodesRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/k8ci.go b/pkg/cloudbroker/k8ci.go index 0d5f260..aacc3d9 100644 --- a/pkg/cloudbroker/k8ci.go +++ b/pkg/cloudbroker/k8ci.go @@ -1,9 +1,10 @@ package cloudbroker import ( - "github.com/rudecs/decort-sdk/pkg/cloudapi/k8ci" + "github.com/rudecs/decort-sdk/pkg/cloudbroker/k8ci" ) +// Accessing the K8CI method group func (cb *CloudBroker) K8CI() *k8ci.K8CI { return k8ci.New(cb.client) } diff --git a/pkg/cloudbroker/k8ci/create.go b/pkg/cloudbroker/k8ci/create.go new file mode 100644 index 0000000..8bb2b6e --- /dev/null +++ b/pkg/cloudbroker/k8ci/create.go @@ -0,0 +1,128 @@ +package k8ci + +import ( + "context" + "errors" + "net/http" + "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" +) + +// Request struct for create K8CI instance +type CreateRequest struct { + // Name of catalog item + // Required: true + Name string `url:"name"` + + // Version tag + // Required: true + Version string `url:"version"` + + // Optional description + // Required: false + Description string `url:"description,omitempty"` + + // Image ID for master K8S node + // Required: true + MasterImageID uint64 `url:"masterImageId"` + + // Compute driver + // Should be one of: + // - KVM_X86 + // - KVM_PPC + // - etc + // Required: true + MasterDriver string `url:"masterDriver"` + + // Image ID for worker K8S node + // Required: true + WorkerImageID uint64 `url:"workerImageId"` + + // Compute driver + // Should be one of + // - KVM_X86 + // - KVM_PPC + // - etc + // Required: true + WorkerDriver string `url:"workerDriver"` + + // Image ID for load balancer node + // Required: true + LBImageID uint64 `url:"lbImageId"` + + // List of account IDs, which have access to this item. + // If empty, any account has access + // Required: false + SharedWith []uint64 `url:"sharedWith,omitempty"` + + // Policy limit on maximum number of master nodes + // Required: true + MaxMasterCount uint64 `url:"maxMasterCount"` + + // Policy limit on maximum number of worker nodes + // Required: true + MaxWorkerCount uint64 `url:"maxWorkerCount"` +} + +func (krq CreateRequest) validate() error { + if krq.Name == "" { + return errors.New("validation-error: field Name must be set") + } + if krq.Version == "" { + return errors.New("validation-error: field Version must be set") + } + if krq.MasterImageID == 0 { + return errors.New("validation-error: field MasterImageID must be set") + } + if krq.MasterDriver == "" { + return errors.New("validation-error: field MasterDriver must be set") + } + if krq.WorkerImageID == 0 { + return errors.New("validation-error: field WorkerImageID must be set") + } + if krq.WorkerDriver == "" { + return errors.New("validation-error: field WorkerDriver must be set") + } + if krq.LBImageID == 0 { + return errors.New("validation-error: field LBImageID must be set") + } + if krq.MaxMasterCount == 0 { + return errors.New("validation-error: field MaxMasterCount must be set") + } + if krq.MaxWorkerCount == 0 { + return errors.New("validation-error: field MaxWorkerCount must be set") + } + validate := validators.StringInSlice(krq.MasterDriver, []string{"KVM_X86", "KVM_PPC"}) + if !validate { + return errors.New("validation-error: field MasterDriver must be one of KVM_X86, KVM_PPC") + } + validate = validators.StringInSlice(krq.WorkerDriver, []string{"KVM_X86", "KVM_PPC"}) + if !validate { + return errors.New("validation-error: field WorkerDriver must be one of KVM_X86, KVM_PPC") + } + + return nil +} + +// Create creates a new K8CI instance +func (k K8CI) Create(ctx context.Context, req CreateRequest) (uint64, error) { + err := req.validate() + if err != nil { + return 0, err + } + + url := "/cloudbroker/k8ci/create" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8ci/delete.go b/pkg/cloudbroker/k8ci/delete.go new file mode 100644 index 0000000..d5315d8 --- /dev/null +++ b/pkg/cloudbroker/k8ci/delete.go @@ -0,0 +1,49 @@ +package k8ci + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete K8CI +type DeleteRequest struct { + // K8CI ID + // Required: true + K8CIID uint64 `url:"k8ciId"` + + // Delete permanently or not + // Required: false + Permanently bool `url:"permanently,omitempty"` +} + +func (krq DeleteRequest) validate() error { + if krq.K8CIID == 0 { + return errors.New("validation-error: field K8CIID must be set") + } + + return nil +} + +// Delete deletes K8CI by ID +func (k K8CI) Delete(ctx context.Context, req DeleteRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8ci/delete" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8ci/disable.go b/pkg/cloudbroker/k8ci/disable.go new file mode 100644 index 0000000..91ed79a --- /dev/null +++ b/pkg/cloudbroker/k8ci/disable.go @@ -0,0 +1,45 @@ +package k8ci + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for disable K8CI +type DisableRequest struct { + // K8CI ID + // Required: true + K8CIID uint64 `url:"k8ciId"` +} + +func (krq DisableRequest) validate() error { + if krq.K8CIID == 0 { + return errors.New("validation-error: field K8CIID must be set") + } + + return nil +} + +// Disable disables K8CI +func (k K8CI) Disable(ctx context.Context, req DisableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8ci/disable" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8ci/enable.go b/pkg/cloudbroker/k8ci/enable.go new file mode 100644 index 0000000..e51fbc7 --- /dev/null +++ b/pkg/cloudbroker/k8ci/enable.go @@ -0,0 +1,45 @@ +package k8ci + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for enable K8CI +type EnableRequest struct { + // K8CI ID + // Required: true + K8CIID uint64 `url:"k8ciId"` +} + +func (krq EnableRequest) validate() error { + if krq.K8CIID == 0 { + return errors.New("validation-error: field K8CIID must be set") + } + + return nil +} + +// Enable enables K8CI +func (k K8CI) Enable(ctx context.Context, req EnableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8ci/enable" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8ci/get.go b/pkg/cloudbroker/k8ci/get.go new file mode 100644 index 0000000..eec815f --- /dev/null +++ b/pkg/cloudbroker/k8ci/get.go @@ -0,0 +1,47 @@ +package k8ci + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get information about K8CI +type GetRequest struct { + // ID of the K8 catalog item to get + // Required: true + K8CIID uint64 `url:"k8ciId"` +} + +func (krq GetRequest) validate() error { + if krq.K8CIID == 0 { + return errors.New("validation-error: field K8CIID must be set") + } + + return nil +} + +// Get gets details of the specified K8 catalog item +func (k K8CI) Get(ctx context.Context, req GetRequest) (*RecordK8CI, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/k8ci/get" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + item := RecordK8CI{} + + err = json.Unmarshal(res, &item) + if err != nil { + return nil, err + } + + return &item, nil +} diff --git a/pkg/cloudbroker/k8ci/k8ci.go b/pkg/cloudbroker/k8ci/k8ci.go new file mode 100644 index 0000000..705278d --- /dev/null +++ b/pkg/cloudbroker/k8ci/k8ci.go @@ -0,0 +1,18 @@ +// API to manage K8CI instances +package k8ci + +import ( + "github.com/rudecs/decort-sdk/interfaces" +) + +// Structure for creating request to K8CI +type K8CI struct { + client interfaces.Caller +} + +// Builder for K8CI endpoints +func New(client interfaces.Caller) *K8CI { + return &K8CI{ + client: client, + } +} diff --git a/pkg/cloudbroker/k8ci/list.go b/pkg/cloudbroker/k8ci/list.go new file mode 100644 index 0000000..e6d006d --- /dev/null +++ b/pkg/cloudbroker/k8ci/list.go @@ -0,0 +1,41 @@ +package k8ci + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get list information about images +type ListRequest struct { + // List disabled items as well + // Required: false + IncludeDisabled bool `url:"includeDisabled,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} + +// List gets list all k8ci catalog items available to the current user +func (k K8CI) List(ctx context.Context, req ListRequest) (ListK8CI, error) { + url := "/cloudbroker/k8ci/list" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListK8CI{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/k8ci/list_deleted.go b/pkg/cloudbroker/k8ci/list_deleted.go new file mode 100644 index 0000000..26d3ae5 --- /dev/null +++ b/pkg/cloudbroker/k8ci/list_deleted.go @@ -0,0 +1,37 @@ +package k8ci + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get list information about deleted images +type ListDeletedRequest struct { + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} + +// ListDeleted gets list all deleted k8ci catalog items available to the current user +func (k K8CI) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListK8CI, error) { + url := "/cloudbroker/k8ci/listDeleted" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListK8CI{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/k8ci/models.go b/pkg/cloudbroker/k8ci/models.go new file mode 100644 index 0000000..9fb36a5 --- /dev/null +++ b/pkg/cloudbroker/k8ci/models.go @@ -0,0 +1,63 @@ +package k8ci + +// Main information about K8CI +type ItemK8CI struct { + // Created time + CreatedTime uint64 `json:"createdTime"` + // Detailed information about K8CI + RecordK8CI +} + +// List K8CI +type ListK8CI []ItemK8CI + +// Detailed information about K8CI +type RecordK8CI struct { + // Description + Description string `json:"desc"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Load balancer image ID + LBImageID uint64 `json:"lbImageId"` + + // Master driver + MasterDriver string `json:"masterDriver"` + + // Master image ID + MasterImageID uint64 `json:"masterImageId"` + + // Max master count + MaxMasterCount uint64 `json:"maxMasterCount"` + + // Max worker count + MaxWorkerCount uint64 `json:"maxWorkerCount"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Shared with + SharedWith []interface{} `json:"sharedWith"` + + // Status + Status string `json:"status"` + + // Version + Version string `json:"version"` + + // Worker driver + WorkerDriver string `json:"workerDriver"` + + // Worker image ID + WorkerImageID uint64 `json:"workerImageId"` +} diff --git a/pkg/cloudbroker/k8ci/restore.go b/pkg/cloudbroker/k8ci/restore.go new file mode 100644 index 0000000..be5db22 --- /dev/null +++ b/pkg/cloudbroker/k8ci/restore.go @@ -0,0 +1,45 @@ +package k8ci + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for restore K8CI +type RestoreRequest struct { + // K8CI ID + // Required: true + K8CIID uint64 `url:"k8ciId"` +} + +func (krq RestoreRequest) validate() error { + if krq.K8CIID == 0 { + return errors.New("validation-error: field K8CIID must be set") + } + + return nil +} + +// Restore restores K8CI +func (k K8CI) Restore(ctx context.Context, req RestoreRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8ci/restore" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8s.go b/pkg/cloudbroker/k8s.go index e21ecbd..fe6d2ea 100644 --- a/pkg/cloudbroker/k8s.go +++ b/pkg/cloudbroker/k8s.go @@ -1,9 +1,10 @@ package cloudbroker import ( - "github.com/rudecs/decort-sdk/pkg/cloudapi/k8s" + "github.com/rudecs/decort-sdk/pkg/cloudbroker/k8s" ) +// Accessing the K8S method group func (cb *CloudBroker) K8S() *k8s.K8S { return k8s.New(cb.client) } diff --git a/pkg/cloudbroker/k8s/create.go b/pkg/cloudbroker/k8s/create.go new file mode 100644 index 0000000..428eecc --- /dev/null +++ b/pkg/cloudbroker/k8s/create.go @@ -0,0 +1,141 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strings" +) + +// Request struct for create K8S +type CreateRequest struct { + // Name of kubernetes cluster + // Required: true + Name string `url:"name"` + + // Resource group ID for cluster placement + // Required: true + RGID uint64 `url:"rgId"` + + // ID of kubernetes catalog item (K8CI) for cluster + // Required: true + K8CIID uint64 `url:"k8ciId"` + + // Name for first worker group created with cluster + // Required: true + WorkerGroupName string `url:"workerGroupName"` + + // ID of SEP to create boot disks for master nodes. + // Uses images SEP ID if not set + // Required: false + MasterSEPID uint64 `url:"masterSepId,omitempty"` + + // Pool to use if master SEP ID is set, can be also empty if needed to be chosen by system + // Required: false + MasterSEPPool string `url:"masterSepPool,omitempty"` + + // ID of SEP to create boot disks for default worker nodes group. + // Uses images SEP ID if not set + // Required: false + WorkerSEPID uint64 `url:"workerSepId,omitempty"` + + // Pool to use if worker SEP ID is set, can be also empty if needed to be chosen by system + // Required: false + WorkerSEPPool string `url:"workerSepPool,omitempty"` + + // List of strings with labels for default worker group + // i.e: ["label1=value1", "label2=value2"] + // Required: false + Labels []string `url:"labels,omitempty"` + + // List of strings with taints for default worker group + // i.e: ["key1=value1:NoSchedule", "key2=value2:NoExecute"] + // Required: false + Taints []string `url:"taints,omitempty"` + + // List of strings with annotations for worker group + // i.e: ["key1=value1", "key2=value2"] + // Required: false + Annotations []string `url:"annotations,omitempty"` + + // Number of master nodes to create + // Required: false + MasterNum uint64 `url:"masterNum,omitempty"` + + // Master node CPU count + // Required: false + MasterCPU uint64 `url:"masterCpu,omitempty"` + + // Master node RAM volume in MB + // Required: false + MasterRAM uint64 `url:"masterRam,omitempty"` + + // Master node boot disk size in GB If 0 is specified, size is defined by the OS image size + // Required: false + MasterDisk uint64 `url:"masterDisk,omitempty"` + + // Number of worker nodes to create in default worker group + // Required: false + WorkerNum uint64 `url:"workerNum,omitempty"` + + // Worker node CPU count + // Required: false + WorkerCPU uint64 `url:"workerCpu,omitempty"` + + // Worker node RAM volume in MB + // Required: false + WorkerRAM uint64 `url:"workerRam,omitempty"` + + // Worker node boot disk size in GB. If 0 is specified, size is defined by the OS image size + // Required: false + WorkerDisk uint64 `url:"workerDisk,omitempty"` + + // ID of the external network to connect load balancer and cluster VINS. If 0 is specified, external network selects automatically to + // Required: false + ExtNetID uint64 `url:"extnetId,omitempty"` + + // Create kubernetes cluster with masters nodes behind load balancer if true. + // Otherwise give all cluster nodes direct external addresses from selected external network + // Required: false + WithLB bool `url:"withLB,omitempty"` + + // Text description of this kubernetes cluster + // Required: false + Description string `url:"desc,omitempty"` +} + +func (krq CreateRequest) validate() error { + if krq.Name == "" { + return errors.New("validation-error: field Name must be set") + } + if krq.RGID == 0 { + return errors.New("validation-error: field RGID must be set") + } + if krq.K8CIID == 0 { + return errors.New("validation-error: field K8CIID must be set") + } + if krq.WorkerGroupName == "" { + return errors.New("validation-error: field WorkerGroupName must be set") + } + + return nil +} + +// Create creates a new kubernetes cluster in the specified resource group +func (k K8S) Create(ctx context.Context, req CreateRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/k8s/create" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/delete.go b/pkg/cloudbroker/k8s/delete.go new file mode 100644 index 0000000..d1fdba7 --- /dev/null +++ b/pkg/cloudbroker/k8s/delete.go @@ -0,0 +1,50 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete kubernetes cluster +type DeleteRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // True if cluster is destroyed permanently. + // Otherwise it can be restored from recycle bin + // Required: true + Permanently bool `url:"permanently"` +} + +func (krq DeleteRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + + return nil +} + +// Delete deletes kubernetes cluster +func (k K8S) Delete(ctx context.Context, req DeleteRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8s/delete" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/delete_master_from_group.go b/pkg/cloudbroker/k8s/delete_master_from_group.go new file mode 100644 index 0000000..9a59fe8 --- /dev/null +++ b/pkg/cloudbroker/k8s/delete_master_from_group.go @@ -0,0 +1,59 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete master from group +type DeleteMasterFromGroupRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // ID of the masters compute group + // Required: true + MasterGroupID uint64 `url:"masterGroupId"` + + // List of Compute IDs of master nodes to delete + // Required: true + MasterIDs []string `url:"masterIds"` +} + +func (krq DeleteMasterFromGroupRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + if krq.MasterGroupID == 0 { + return errors.New("validation-error: field MasterGroupID must be set") + } + if len(krq.MasterIDs) == 0 { + return errors.New("validation-error: field MasterIDs must be set") + } + + return nil +} + +// DeleteMasterFromGroup deletes compute from masters group in selected kubernetes cluster +func (k K8S) DeleteMasterFromGroup(ctx context.Context, req DeleteMasterFromGroupRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8s/deleteMasterFromGroup" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/delete_worker_from_group.go b/pkg/cloudbroker/k8s/delete_worker_from_group.go new file mode 100644 index 0000000..04af01e --- /dev/null +++ b/pkg/cloudbroker/k8s/delete_worker_from_group.go @@ -0,0 +1,59 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete worker from group +type DeleteWorkerFromGroupRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // ID of the workers compute group + // Required: true + WorkersGroupID uint64 `url:"workersGroupId"` + + // Compute ID of worker node to delete + // Required: true + WorkerID uint64 `url:"workerId"` +} + +func (krq DeleteWorkerFromGroupRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + if krq.WorkersGroupID == 0 { + return errors.New("validation-error: field WorkerGroupID must be set") + } + if krq.WorkerID == 0 { + return errors.New("validation-error: field WorkerIDs must be set") + } + + return nil +} + +// DeleteWorkerFromGroup deletes worker compute from workers group in selected kubernetes cluster +func (k K8S) DeleteWorkerFromGroup(ctx context.Context, req DeleteWorkerFromGroupRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8s/deleteWorkerFromGroup" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/disable.go b/pkg/cloudbroker/k8s/disable.go new file mode 100644 index 0000000..8bbf684 --- /dev/null +++ b/pkg/cloudbroker/k8s/disable.go @@ -0,0 +1,45 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for disable kubernetes cluster +type DisableRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` +} + +func (krq DisableRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + + return nil +} + +// Disable disables kubernetes cluster by ID +func (k K8S) Disable(ctx context.Context, req DisableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8s/disable" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/enable.go b/pkg/cloudbroker/k8s/enable.go new file mode 100644 index 0000000..4893414 --- /dev/null +++ b/pkg/cloudbroker/k8s/enable.go @@ -0,0 +1,45 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for enable kubernetes cluster +type EnableRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` +} + +func (krq EnableRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + + return nil +} + +// Enable enables kubernetes cluster by ID +func (k K8S) Enable(ctx context.Context, req EnableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8s/enable" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/find_group_by_label.go b/pkg/cloudbroker/k8s/find_group_by_label.go new file mode 100644 index 0000000..27260fc --- /dev/null +++ b/pkg/cloudbroker/k8s/find_group_by_label.go @@ -0,0 +1,59 @@ +package k8s + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get information about group of kubernetes cluster +type FindGroupByLabelRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // List of labels to search + // Required: true + Labels []string `url:"labels"` + + // If true and more than one label provided, select only groups that have all provided labels. + // If false - groups that have at least one label + // Required: true + Strict bool `url:"strict"` +} + +func (krq FindGroupByLabelRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + if len(krq.Labels) == 0 { + return errors.New("validation-error: field Labels must be set") + } + + return nil +} + +// FindGroupByLabel find worker group information by one on more labels +func (k K8S) FindGroupByLabel(ctx context.Context, req FindGroupByLabelRequest) (ListK8SGroup, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/k8s/findGroupByLabel" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListK8SGroup{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/k8s/get.go b/pkg/cloudbroker/k8s/get.go new file mode 100644 index 0000000..56436b3 --- /dev/null +++ b/pkg/cloudbroker/k8s/get.go @@ -0,0 +1,47 @@ +package k8s + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get detailed information about kubernetes cluster +type GetRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` +} + +func (krq GetRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + + return nil +} + +// Get gets information about kubernetes cluster +func (k K8S) Get(ctx context.Context, req GetRequest) (*RecordK8S, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/k8s/get" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + info := RecordK8S{} + + err = json.Unmarshal(res, &info) + if err != nil { + return nil, err + } + + return &info, nil +} diff --git a/pkg/cloudbroker/k8s/get_config.go b/pkg/cloudbroker/k8s/get_config.go new file mode 100644 index 0000000..d4db031 --- /dev/null +++ b/pkg/cloudbroker/k8s/get_config.go @@ -0,0 +1,42 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strings" +) + +// Request struct for get configuration of kubernetes cluster +type GetConfigRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` +} + +func (krq GetConfigRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + + return nil +} + +// GetConfig gets configuration data to access kubernetes cluster +func (k K8S) GetConfig(ctx context.Context, req GetConfigRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/k8s/getConfig" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/get_node_annotations.go b/pkg/cloudbroker/k8s/get_node_annotations.go new file mode 100644 index 0000000..d067626 --- /dev/null +++ b/pkg/cloudbroker/k8s/get_node_annotations.go @@ -0,0 +1,49 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strings" +) + +// Request struct for get node annotations +type GetNodeAnnotationsRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // Node ID + // Required: true + NodeID uint64 `url:"nodeId"` +} + +func (krq GetNodeAnnotationsRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID can not be empty or equal to 0") + } + if krq.NodeID == 0 { + return errors.New("validation-error: field NodeID can not be empty or equal to 0") + } + + return nil +} + +// GetNodeAnnotations gets kubernetes cluster worker node annotations +func (k K8S) GetNodeAnnotations(ctx context.Context, req GetNodeAnnotationsRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/k8s/getNodeAnnotations" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/get_node_labels.go b/pkg/cloudbroker/k8s/get_node_labels.go new file mode 100644 index 0000000..c146ece --- /dev/null +++ b/pkg/cloudbroker/k8s/get_node_labels.go @@ -0,0 +1,49 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strings" +) + +// Request struct for get worker node labels +type GetNodeLabelsRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // Compute ID of worker node + // Required: true + NodeID uint64 `url:"nodeId"` +} + +func (krq GetNodeLabelsRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID can not be empty or equal to 0") + } + if krq.NodeID == 0 { + return errors.New("validation-error: field NodeID can not be empty or equal to 0") + } + + return nil +} + +// GetNodeLabels gets kubernetes cluster worker node labels +func (k K8S) GetNodeLabels(ctx context.Context, req GetNodeLabelsRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/k8s/getNodeLabels" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/get_node_taints.go b/pkg/cloudbroker/k8s/get_node_taints.go new file mode 100644 index 0000000..58a7d02 --- /dev/null +++ b/pkg/cloudbroker/k8s/get_node_taints.go @@ -0,0 +1,49 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strings" +) + +// Request struct for get node taints +type GetNodeTaintsRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // Node ID + // Required: false + NodeID uint64 `url:"nodeId"` +} + +func (krq GetNodeTaintsRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID can not be empty or equal to 0") + } + if krq.NodeID == 0 { + return errors.New("validation-error: field NodeID can not be empty or equal to 0") + } + + return nil +} + +// GetNodeTaints gets kubernetes cluster worker node taints +func (k K8S) GetNodeTaints(ctx context.Context, req GetNodeTaintsRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/k8s/getNodeTaints" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/k8s.go b/pkg/cloudbroker/k8s/k8s.go new file mode 100644 index 0000000..0c5a03d --- /dev/null +++ b/pkg/cloudbroker/k8s/k8s.go @@ -0,0 +1,18 @@ +// API for kubernetes clusters management +package k8s + +import ( + "github.com/rudecs/decort-sdk/interfaces" +) + +// Structure for creating request to K8S +type K8S struct { + client interfaces.Caller +} + +// Builder for K8S endpoints +func New(client interfaces.Caller) *K8S { + return &K8S{ + client: client, + } +} diff --git a/pkg/cloudbroker/k8s/list.go b/pkg/cloudbroker/k8s/list.go new file mode 100644 index 0000000..02d3896 --- /dev/null +++ b/pkg/cloudbroker/k8s/list.go @@ -0,0 +1,42 @@ +package k8s + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get list information K8S +type ListRequest struct { + // Include deleted clusters in result + // Required: false + IncludeDeleted bool `url:"includedeleted,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} + +// List gets list all kubernetes clusters +func (k K8S) List(ctx context.Context, req ListRequest) (ListK8S, error) { + + url := "/cloudbroker/k8s/list" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListK8S{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/k8s/list_deleted.go b/pkg/cloudbroker/k8s/list_deleted.go new file mode 100644 index 0000000..e1003c7 --- /dev/null +++ b/pkg/cloudbroker/k8s/list_deleted.go @@ -0,0 +1,38 @@ +package k8s + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get list deleted kubernetes cluster +type ListDeletedRequest struct { + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} + +// ListDeleted gets all deleted kubernetes clusters +func (k K8S) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListK8S, error) { + + url := "/cloudbroker/k8s/listDeleted" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListK8S{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/k8s/models.go b/pkg/cloudbroker/k8s/models.go new file mode 100644 index 0000000..e473e4e --- /dev/null +++ b/pkg/cloudbroker/k8s/models.go @@ -0,0 +1,292 @@ +package k8s + +// Deteiled information +type ItemDetailedInfo struct { + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Status + Status string `json:"status"` + + // Status + TechStatus string `json:"techStatus"` +} + +// List detailed information +type ListDetailedInfo []ItemDetailedInfo + +// Detailed information about K8S group +type RecordK8SGroup struct { + // List annotations + Annotations []string `json:"annotations"` + + // Number of CPU + CPU uint64 `json:"cpu"` + + // List detailed information + DetailedInfo ListDetailedInfo `json:"detailedInfo"` + + // Disk + Disk uint64 `json:"disk"` + + // GUID + GUID string `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // List labels + Labels []string `json:"labels"` + + // Name + Name string `json:"name"` + + // Number + Num uint64 `json:"num"` + + // Number of RAM + RAM uint64 `json:"ram"` + + // List taints + Taints []string `json:"taints"` +} + +// List K8S groups +type ListK8SGroup []RecordK8SGroup + +// Detailed information about K8S +type RecordK8S struct { + // Access Control List + ACL RecordACLGroup `json:"ACL"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Basic service ID + BServiceID uint64 `json:"bserviceId"` + + // CI ID + CIID uint64 `json:"ciId"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // ID + ID uint64 `json:"id"` + + // K8CI name + K8CIName string `json:"k8ciName"` + + // Detailed information about K8S groups + K8SGroups RecordK8SGroups `json:"k8sGroups"` + + // Load balancer ID + LBID uint64 `json:"lbId"` + + // Name + Name string `json:"name"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` +} + +// Detailed info about K8S groups +type RecordK8SGroups struct { + // Master group + Masters MasterGroup `json:"masters"` + + // Worker group + Workers ListK8SGroup `json:"workers"` +} + +// Detailed information about master group +type MasterGroup struct { + // Number of CPU + CPU uint64 `json:"cpu"` + + // Detailed information + DetailedInfo ListDetailedInfo `json:"detailedInfo"` + + // Disk + Disk uint64 `json:"disk"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Number + Num uint64 `json:"num"` + + // Number of RAM + RAM uint64 `json:"ram"` +} + +// Detailed information of access control +type RecordACLGroup struct { + // Account ACL + AccountACL ListACL `json:"accountAcl"` + + // K8S ACL + K8SACL ListACL `json:"k8sAcl"` + + // RG ACL + RGACL ListACL `json:"rgAcl"` +} + +// Access Control List +type ACL struct { + // Explicit + Explicit bool `json:"explicit"` + + // GUID + GUID string `json:"guid"` + + // Right + Right string `json:"right"` + + // Status + Status string `json:"status"` + + // Type + Type string `json:"type"` + + // User group ID + UserGroupID string `json:"userGroupId"` +} + +// List ACL +type ListACL []ACL + +// Main information about K8S +type ItemK8S struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Access Control List + ACL []interface{} `json:"acl"` + + // Basic service ID + BServiceID uint64 `json:"bserviceId"` + + // CI ID + CIID uint64 `json:"ciId"` + + // Config + Config interface{} `json:"config"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // External network ID + ExtNetID uint64 `json:"extnetId"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Load balancer ID + LBID uint64 `json:"lbId"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Service account + ServiceAccount ServiceAccount `json:"serviceAccount"` + + // SSH key + SSHKey string `json:"sshKey"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // VINS ID + VINSID uint64 `json:"vinsId"` + + // List workers + WorkersGroup ListK8SGroup `json:"workersGroups"` +} + +// Service account +type ServiceAccount struct { + // GUID + GUID string `json:"guid"` + + // Password + Password string `json:"password"` + + // Username + Username string `json:"username"` +} + +// List K8S +type ListK8S []ItemK8S diff --git a/pkg/cloudbroker/k8s/restore.go b/pkg/cloudbroker/k8s/restore.go new file mode 100644 index 0000000..d0c6bd9 --- /dev/null +++ b/pkg/cloudbroker/k8s/restore.go @@ -0,0 +1,45 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for restore kubernetes cluster +type RestoreRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` +} + +func (krq RestoreRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + + return nil +} + +// Restore restore kubernetes cluster from recycle bin +func (k K8S) Restore(ctx context.Context, req RestoreRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8s/restore" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/start.go b/pkg/cloudbroker/k8s/start.go new file mode 100644 index 0000000..8a09825 --- /dev/null +++ b/pkg/cloudbroker/k8s/start.go @@ -0,0 +1,45 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for start kubernetes cluster +type StartRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` +} + +func (krq StartRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + + return nil +} + +// Start starts kubernetes cluster by ID +func (k K8S) Start(ctx context.Context, req StartRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8s/start" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/stop.go b/pkg/cloudbroker/k8s/stop.go new file mode 100644 index 0000000..3d6611c --- /dev/null +++ b/pkg/cloudbroker/k8s/stop.go @@ -0,0 +1,45 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for stop kubernetes cluster +type StopRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` +} + +func (krq StopRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + + return nil +} + +// Stop stops kubernetes cluster by ID +func (k K8S) Stop(ctx context.Context, req StopRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8s/stop" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/update.go b/pkg/cloudbroker/k8s/update.go new file mode 100644 index 0000000..fdda541 --- /dev/null +++ b/pkg/cloudbroker/k8s/update.go @@ -0,0 +1,55 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for update kubernetes cluster +type UpdateRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // New name to set. + // If empty string is passed, name is not updated + // Required: false + Name string `url:"name,omitempty"` + + // New description to set. + // If empty string is passed, description is not updated + // Required: false + Description string `url:"desc,omitempty"` +} + +func (krq UpdateRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + + return nil +} + +// Update updates name or description of kubernetes cluster +func (k K8S) Update(ctx context.Context, req UpdateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8s/update" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/worker_add.go b/pkg/cloudbroker/k8s/worker_add.go new file mode 100644 index 0000000..8ce9b14 --- /dev/null +++ b/pkg/cloudbroker/k8s/worker_add.go @@ -0,0 +1,58 @@ +package k8s + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for add worker to a kubernetes cluster +type WorkerAddRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // ID of the workers compute group + // Required: true + WorkersGroupID uint64 `url:"workersGroupId"` + + // How many worker nodes to add + // Required: true + Num uint64 `url:"num"` +} + +func (krq WorkerAddRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + if krq.WorkersGroupID == 0 { + return errors.New("validation-error: field WorkersGroupID must be set") + } + + return nil +} + +// WorkerAdd adds worker nodes to a kubernetes cluster +func (k K8S) WorkerAdd(ctx context.Context, req WorkerAddRequest) ([]uint64, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/k8s/workerAdd" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + result := make([]uint64, 0) + + err = json.Unmarshal(res, &result) + if err != nil { + return nil, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/worker_reset.go b/pkg/cloudbroker/k8s/worker_reset.go new file mode 100644 index 0000000..360eb5d --- /dev/null +++ b/pkg/cloudbroker/k8s/worker_reset.go @@ -0,0 +1,59 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for hard reset kubernetes cluster +type WorkerResetRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // ID of the workers compute group + // Required: true + WorkersGroupID uint64 `url:"workersGroupId"` + + // Compute ID of worker node to reset + // Required: true + WorkerID uint64 `url:"workerId"` +} + +func (krq WorkerResetRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + if krq.WorkersGroupID == 0 { + return errors.New("validation-error: field WorkersGroupID must be set") + } + if krq.WorkerID == 0 { + return errors.New("validation-error: field WorkerID must be set") + } + + return nil +} + +// WorkerReset hard reset (compute start + stop) worker node of the kubernetes cluster +func (k K8S) WorkerReset(ctx context.Context, req WorkerResetRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8s/workerReset" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/worker_restart.go b/pkg/cloudbroker/k8s/worker_restart.go new file mode 100644 index 0000000..8e4d3d8 --- /dev/null +++ b/pkg/cloudbroker/k8s/worker_restart.go @@ -0,0 +1,58 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for restart worker node +type WorkerRestartRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // ID of the workers compute group + // Required: true + WorkersGroupID uint64 `url:"workersGroupId"` + + // Compute ID of worker node to restart + // Required: true + WorkerID uint64 `url:"workerId"` +} + +func (krq WorkerRestartRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + if krq.WorkersGroupID == 0 { + return errors.New("validation-error: field WorkersGroupID must be set") + } + if krq.WorkerID == 0 { + return errors.New("validation-error: field WorkerID must be set") + } + + return nil +} + +// WorkerRestart soft restart (reboot OS) worker node of the kubernetes cluster +func (k8s K8S) WorkerRestart(ctx context.Context, req WorkerRestartRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8s/workerRestart" + + res, err := k8s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + return result, nil +} diff --git a/pkg/cloudbroker/k8s/workers_group_add.go b/pkg/cloudbroker/k8s/workers_group_add.go new file mode 100644 index 0000000..b95033f --- /dev/null +++ b/pkg/cloudbroker/k8s/workers_group_add.go @@ -0,0 +1,90 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strings" +) + +// Request struct for add workers group +type WorkersGroupAddRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // Worker group name + // Required: true + Name string `url:"name"` + + // ID of SEP to create boot disks for default worker nodes group. + // Uses images SEP ID if not set + // Required: false + WorkerSEPID uint64 `url:"workerSepId,omitempty"` + + // Pool to use if worker SEP ID is set, can be also empty if + // needed to be chosen by system + // Required: false + WorkerSEPPool string `url:"workerSepPool,omitempty"` + + // List of strings with labels for worker group + // i.e: ["label1=value1", "label2=value2"] + // Required: false + Labels []string `url:"labels,omitempty"` + + // List of strings with taints for worker group + // i.e: ["key1=value1:NoSchedule", "key2=value2:NoExecute"] + // Required: false + Taints []string `url:"taints,omitempty"` + + // List of strings with annotations for worker group + // i.e: ["key1=value1", "key2=value2"] + // Required: false + Annotations []string `url:"annotations,omitempty"` + + // Number of worker nodes to create + // Required: false + WorkerNum uint64 `url:"workerNum,omitempty"` + + // Worker node CPU count + // Required: false + WorkerCPU uint64 `url:"workerCpu,omitempty"` + + // Worker node RAM volume in MB + // Required: false + WorkerRAM uint64 `url:"workerRam,omitempty"` + + // Worker node boot disk size in GB If 0 is specified, size is defined by the OS image size + // Required: false + WorkerDisk uint64 `url:"workerDisk,omitempty"` +} + +func (krq WorkersGroupAddRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + if krq.Name == "" { + return errors.New("validation-error: field Name must be set") + } + + return nil +} + +// WorkersGroupAdd adds workers group to kubernetes cluster +func (k K8S) WorkersGroupAdd(ctx context.Context, req WorkersGroupAddRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/k8s/workersGroupAdd" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/workers_group_delete.go b/pkg/cloudbroker/k8s/workers_group_delete.go new file mode 100644 index 0000000..1800288 --- /dev/null +++ b/pkg/cloudbroker/k8s/workers_group_delete.go @@ -0,0 +1,52 @@ +package k8s + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete workers group +type WorkersGroupDeleteRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // Worker group ID + // Required: true + WorkersGroupID uint64 `url:"workersGroupId"` +} + +func (krq WorkersGroupDeleteRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + if krq.WorkersGroupID == 0 { + return errors.New("validation-error: field WorkersGroupID must be set") + } + + return nil +} + +// WorkersGroupDelete deletes workers group from kubernetes cluster +func (k K8S) WorkersGroupDelete(ctx context.Context, req WorkersGroupDeleteRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/k8s/workersGroupDelete" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/k8s/workers_group_get_by_name.go b/pkg/cloudbroker/k8s/workers_group_get_by_name.go new file mode 100644 index 0000000..861b3cd --- /dev/null +++ b/pkg/cloudbroker/k8s/workers_group_get_by_name.go @@ -0,0 +1,54 @@ +package k8s + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get information about worker group +type WorkersGroupGetByNameRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId"` + + // Worker group name + // Required: true + GroupName string `url:"groupName"` +} + +func (krq WorkersGroupGetByNameRequest) validate() error { + if krq.K8SID == 0 { + return errors.New("validation-error: field K8SID must be set") + } + if krq.GroupName == "" { + return errors.New("validation-error: field WorkersGroupID must be set") + } + + return nil +} + +// WorkersGroupGetByName gets worker group metadata by name +func (k K8S) WorkersGroupGetByName(ctx context.Context, req WorkersGroupGetByNameRequest) (*RecordK8SGroup, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/k8s/workersGroupGetByName" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + info := RecordK8SGroup{} + + err = json.Unmarshal(res, &info) + if err != nil { + return nil, err + } + + return &info, nil +} diff --git a/pkg/cloudbroker/kvmppc.go b/pkg/cloudbroker/kvmppc.go index 01175c9..abba4ce 100644 --- a/pkg/cloudbroker/kvmppc.go +++ b/pkg/cloudbroker/kvmppc.go @@ -2,6 +2,7 @@ package cloudbroker import "github.com/rudecs/decort-sdk/pkg/cloudbroker/kvmppc" +// Accessing the KVMPPC method group func (cb *CloudBroker) KVMPPC() *kvmppc.KVMPPC { return kvmppc.New(cb.client) } diff --git a/pkg/cloudbroker/kvmppc/create.go b/pkg/cloudbroker/kvmppc/create.go index 11f0db8..fe42142 100644 --- a/pkg/cloudbroker/kvmppc/create.go +++ b/pkg/cloudbroker/kvmppc/create.go @@ -7,28 +7,92 @@ import ( "strconv" ) +// Request struct for create KVM PowerPC VM type CreateRequest struct { - RGID uint64 `url:"rgId"` - Name string `url:"name"` - CPU uint64 `url:"cpu"` - RAM uint64 `url:"ram"` - ImageID uint64 `url:"imageId"` + // ID of the resource group, which will own this VM + // Required: true + RGID uint64 `url:"rgId"` + + // Name of this VM. + // Must be unique among all VMs (including those in DELETED state) in target resource group + // Required: true + Name string `url:"name"` + + // Number CPUs to allocate to this VM + // Required: true + CPU uint64 `url:"cpu"` + + // Volume of RAM in MB to allocate to this VM + // Required: true + RAM uint64 `url:"ram"` + + // ID of the OS image to base this VM on; + // Could be boot disk image or CD-ROM image + // Required: true + ImageID uint64 `url:"imageId"` + + // Size of the boot disk in GB + // Required: false BootDisk uint64 `url:"bootDisk,omitempty"` - SepID uint64 `url:"sepId,omitempty"` - Pool string `url:"pool,omitempty"` - NetType string `url:"netType,omitempty"` - NetID uint64 `url:"netId,omitempty"` - IPAddr string `url:"ipAddr,omitempty"` - UserData string `url:"userdata,omitempty"` - Desc string `url:"desc,omitempty"` - Start bool `url:"start,omitempty"` - StackID uint64 `url:"stackId,omitempty"` - IS string `url:"IS,omitempty"` - IpaType string `url:"ipaType,omitempty"` - Reason string `url:"reason,omitempty"` + + // ID of SEP to create boot disk on. + // Uses images SEP ID if not set + // Required: false + SEPID uint64 `url:"sepId,omitempty"` + + // Pool to use if SEP ID is set, can be also empty if needed to be chosen by system + // Required: false + Pool string `url:"pool,omitempty"` + + // Network type + // Should be one of: + // - VINS + // - EXTNET + // - NONE + // Required: false + NetType string `url:"netType,omitempty"` + + // Network ID for connect to, + // for EXTNET - external network ID, + // for VINS - VINS ID, + // when network type is not "NONE" + // Required: false + NetID uint64 `url:"netId,omitempty"` + + // IP address to assign to this VM when connecting to the specified network + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // Input data for cloud-init facility + // Required: false + Userdata string `url:"userdata,omitempty"` + + // Text description of this VM + // Required: false + Description string `url:"desc,omitempty"` + + // Start VM upon success + // Required: false + Start bool `url:"start,omitempty"` + + // Stack ID + // Required: false + StackID uint64 `url:"stackId,omitempty"` + + // System name + // Required: false + IS string `url:"IS,omitempty"` + + // Compute purpose + // Required: false + IPAType string `url:"ipaType,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` } -func (krq CreateRequest) Validate() error { +func (krq CreateRequest) validate() error { if krq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -48,8 +112,9 @@ func (krq CreateRequest) Validate() error { return nil } +// Create creates KVM PowerPC VM based on specified OS image func (k KVMPPC) Create(ctx context.Context, req CreateRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } diff --git a/pkg/cloudbroker/kvmppc/create_blank.go b/pkg/cloudbroker/kvmppc/create_blank.go index 31db970..6288097 100644 --- a/pkg/cloudbroker/kvmppc/create_blank.go +++ b/pkg/cloudbroker/kvmppc/create_blank.go @@ -7,21 +7,63 @@ import ( "strconv" ) +// Request struct for create KVM PowerPC VM from scratch type CreateBlankRequest struct { - RGID uint64 `url:"rgId"` - Name string `url:"name"` - CPU uint64 `url:"cpu"` - RAM uint64 `url:"ram"` + // ID of the resource group, which will own this VM + // Required: true + RGID uint64 `url:"rgId"` + + // Name of this VM. + // Must be unique among all VMs (including those in DELETED state) in target resource group + // Required: true + Name string `url:"name"` + + // Number CPUs to allocate to this VM + // Required: true + CPU uint64 `url:"cpu"` + + // Volume of RAM in MB to allocate to this VM + // Required: true + RAM uint64 `url:"ram"` + + // Size of the boot disk in GB + // Required: true BootDisk uint64 `url:"bootDisk"` - SepID uint64 `url:"sepId"` - Pool string `url:"pool"` - NetType string `url:"netType,omitempty"` - NetID uint64 `url:"netId,omitempty"` - IPAddr string `url:"ipAddr,omitempty"` - Desc string `url:"desc,omitempty"` + + // ID of SEP to create boot disk on. + // Uses images SEP ID if not set + // Required: true + SEPID uint64 `url:"sepId"` + + // Pool to use if SEP ID is set, can be also empty if needed to be chosen by system + // Required: true + Pool string `url:"pool"` + + // Network type + // Should be one of: + // - VINS + // - EXTNET + // - NONE + // Required: false + NetType string `url:"netType,omitempty"` + + // Network ID for connect to, + // for EXTNET - external network ID, + // for VINS - VINS ID, + // when network type is not "NONE" + // Required: false + NetID uint64 `url:"netId,omitempty"` + + // IP address to assign to this VM when connecting to the specified network + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // Text description of this VM + // Required: false + Description string `url:"desc,omitempty"` } -func (krq CreateBlankRequest) Validate() error { +func (krq CreateBlankRequest) validate() error { if krq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -37,7 +79,7 @@ func (krq CreateBlankRequest) Validate() error { if krq.BootDisk == 0 { return errors.New("validation-error: field BootDisk must be set") } - if krq.SepID == 0 { + if krq.SEPID == 0 { return errors.New("validation-error: field SepID must be set") } if krq.Pool == "" { @@ -47,8 +89,9 @@ func (krq CreateBlankRequest) Validate() error { return nil } +// CreateBlank creates KVM PowerPC VM from scratch func (k KVMPPC) CreateBlank(ctx context.Context, req CreateBlankRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } diff --git a/pkg/cloudbroker/kvmppc/kvmppc.go b/pkg/cloudbroker/kvmppc/kvmppc.go index 8ae640d..89ddebd 100644 --- a/pkg/cloudbroker/kvmppc/kvmppc.go +++ b/pkg/cloudbroker/kvmppc/kvmppc.go @@ -1,11 +1,14 @@ +// API to manage KVM PowerPC compute instances (PPC VMs) package kvmppc import "github.com/rudecs/decort-sdk/interfaces" +// Structure for creating request to KVMPPC type KVMPPC struct { client interfaces.Caller } +// Builder for KVMPPC endpoints func New(client interfaces.Caller) *KVMPPC { return &KVMPPC{ client: client, diff --git a/pkg/cloudbroker/kvmppc/mass_create.go b/pkg/cloudbroker/kvmppc/mass_create.go index 95850cd..de8db28 100644 --- a/pkg/cloudbroker/kvmppc/mass_create.go +++ b/pkg/cloudbroker/kvmppc/mass_create.go @@ -7,26 +7,79 @@ import ( "net/http" ) +// Request struct for mass create KVM PowerPC type MassCreateRequest struct { - RGID uint64 `url:"rgId"` - Name string `url:"name"` - Count uint64 `url:"count"` - CPU uint64 `url:"cpu"` - RAM uint64 `url:"ram"` - ImageID uint64 `url:"imageId"` - BootDisk uint64 `url:"bootDisk,omitempty"` - SepID uint64 `url:"sepId,omitempty"` - Pool string `url:"pool,omitempty"` - NetType string `url:"netType,omitempty"` - NetID uint64 `url:"netId,omitempty"` - IPAddr string `url:"ipAddr,omitempty"` - UserData string `url:"userdata,omitempty"` - Desc string `url:"desc,omitempty"` - Start bool `url:"start,omitempty"` - Reason string `url:"reason,omitempty"` + // ID of the resource group, which will own this VM + // Required: true + RGID uint64 `url:"rgId"` + + // Name of this VM. + // Must be unique among all VMs (including those in DELETED state) in target resource group + // Required: true + Name string `url:"name"` + + // Number of VMs + // Required: true + Count uint64 `url:"count"` + + // Number CPUs to allocate to this VM + // Required: true + CPU uint64 `url:"cpu"` + + // Volume of RAM in MB to allocate to this VM + // Required: true + RAM uint64 `url:"ram"` + + // Image ID + // Required: true + ImageID uint64 `url:"imageId"` + + // Size of the boot disk in GB + // Required: true + BootDisk uint64 `url:"bootDisk"` + + // ID of SEP to create boot disk on. + // Uses images SEP ID if not set + // Required: true + SEPID uint64 `url:"sepId"` + + // Pool to use if SEP ID is set, can be also empty if needed to be chosen by system + // Required: true + Pool string `url:"pool"` + + // Network type + // Should be one of: + // - VINS + // - EXTNET + // - NONE + // Required: false + NetType string `url:"netType,omitempty"` + + // Network ID for connect to, + // for EXTNET - external network ID, + // for VINS - VINS ID, + // when network type is not "NONE" + // Required: false + NetID uint64 `url:"netId,omitempty"` + + // IP address to assign to this VM when connecting to the specified network + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // Text description of this VM + // Required: false + Description string `url:"desc,omitempty"` + + // Start after create of not + // Required: false + Start bool `url:"start,omitempty"` + + // Reason to action + // Required: false + Reason string `url:"reason,omitempty"` } -func (krq MassCreateRequest) Validate() error { +func (krq MassCreateRequest) validate() error { if krq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -49,8 +102,9 @@ func (krq MassCreateRequest) Validate() error { return nil } +// MassCreate creates KVM PPC computes based on specified OS image func (k KVMPPC) MassCreate(ctx context.Context, req MassCreateRequest) ([]uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return nil, err } diff --git a/pkg/cloudbroker/kvmx86.go b/pkg/cloudbroker/kvmx86.go index 5549f3d..f9e7d50 100644 --- a/pkg/cloudbroker/kvmx86.go +++ b/pkg/cloudbroker/kvmx86.go @@ -4,6 +4,7 @@ import ( "github.com/rudecs/decort-sdk/pkg/cloudbroker/kvmx86" ) +// Accessing the KVMX86 method group func (cb *CloudBroker) KVMX86() *kvmx86.KVMX86 { return kvmx86.New(cb.client) } diff --git a/pkg/cloudbroker/kvmx86/create.go b/pkg/cloudbroker/kvmx86/create.go index 04d4e5b..9aec1bf 100644 --- a/pkg/cloudbroker/kvmx86/create.go +++ b/pkg/cloudbroker/kvmx86/create.go @@ -7,28 +7,92 @@ import ( "strconv" ) +// Request struct for create KVM x86 VM type CreateRequest struct { - RGID uint64 `url:"rgId"` - Name string `url:"name"` - CPU uint64 `url:"cpu"` - RAM uint64 `url:"ram"` - ImageID uint64 `url:"imageId"` + // ID of the resource group, which will own this VM + // Required: true + RGID uint64 `url:"rgId"` + + // Name of this VM. + // Must be unique among all VMs (including those in DELETED state) in target resource group + // Required: true + Name string `url:"name"` + + // Number CPUs to allocate to this VM + // Required: true + CPU uint64 `url:"cpu"` + + // Volume of RAM in MB to allocate to this VM + // Required: true + RAM uint64 `url:"ram"` + + // ID of the OS image to base this VM on; + // Could be boot disk image or CD-ROM image + // Required: true + ImageID uint64 `url:"imageId"` + + // Size of the boot disk in GB + // Required: false BootDisk uint64 `url:"bootDisk,omitempty"` - SepID uint64 `url:"sepId,omitempty"` - Pool string `url:"pool,omitempty"` - NetType string `url:"netType,omitempty"` - NetID uint64 `url:"netId,omitempty"` - IPAddr string `url:"ipAddr,omitempty"` - UserData string `url:"userdata,omitempty"` - Desc string `url:"desc,omitempty"` - Start bool `url:"start,omitempty"` - StackID uint64 `url:"stackId,omitempty"` - IS string `url:"IS,omitempty"` - IpaType string `url:"ipaType,omitempty"` - Reason string `url:"reason,omitempty"` + + // ID of SEP to create boot disk on. + // Uses images SEP ID if not set + // Required: false + SEPID uint64 `url:"sepId,omitempty"` + + // Pool to use if SEP ID is set, can be also empty if needed to be chosen by system + // Required: false + Pool string `url:"pool,omitempty"` + + // Network type + // Should be one of: + // - VINS + // - EXTNET + // - NONE + // Required: false + NetType string `url:"netType,omitempty"` + + // Network ID for connect to, + // for EXTNET - external network ID, + // for VINS - VINS ID, + // when network type is not "NONE" + // Required: false + NetID uint64 `url:"netId,omitempty"` + + // IP address to assign to this VM when connecting to the specified network + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // Input data for cloud-init facility + // Required: false + Userdata string `url:"userdata,omitempty"` + + // Text description of this VM + // Required: false + Description string `url:"desc,omitempty"` + + // Start VM upon success + // Required: false + Start bool `url:"start,omitempty"` + + // Stack ID + // Required: false + StackID uint64 `url:"stackId,omitempty"` + + // System name + // Required: false + IS string `url:"IS,omitempty"` + + // Compute purpose + // Required: false + IPAType string `url:"ipaType,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` } -func (krq CreateRequest) Validate() error { +func (krq CreateRequest) validate() error { if krq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -48,8 +112,9 @@ func (krq CreateRequest) Validate() error { return nil } +// Create creates KVM PowerPC VM based on specified OS image func (k KVMX86) Create(ctx context.Context, req CreateRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } @@ -67,4 +132,4 @@ func (k KVMX86) Create(ctx context.Context, req CreateRequest) (uint64, error) { } return result, nil -} \ No newline at end of file +} diff --git a/pkg/cloudbroker/kvmx86/create_blank.go b/pkg/cloudbroker/kvmx86/create_blank.go index 77d4202..24e0b8f 100644 --- a/pkg/cloudbroker/kvmx86/create_blank.go +++ b/pkg/cloudbroker/kvmx86/create_blank.go @@ -7,21 +7,63 @@ import ( "strconv" ) +// Request struct for create KVM x86 VM from scratch type CreateBlankRequest struct { - RGID uint64 `url:"rgId"` - Name string `url:"name"` - CPU uint64 `url:"cpu"` - RAM uint64 `url:"ram"` + // ID of the resource group, which will own this VM + // Required: true + RGID uint64 `url:"rgId"` + + // Name of this VM. + // Must be unique among all VMs (including those in DELETED state) in target resource group + // Required: true + Name string `url:"name"` + + // Number CPUs to allocate to this VM + // Required: true + CPU uint64 `url:"cpu"` + + // Volume of RAM in MB to allocate to this VM + // Required: true + RAM uint64 `url:"ram"` + + // Size of the boot disk in GB + // Required: true BootDisk uint64 `url:"bootDisk"` - SepID uint64 `url:"sepId"` - Pool string `url:"pool"` - NetType string `url:"netType,omitempty"` - NetID uint64 `url:"netId,omitempty"` - IPAddr string `url:"ipAddr,omitempty"` - Desc string `url:"desc,omitempty"` + + // ID of SEP to create boot disk on. + // Uses images SEP ID if not set + // Required: true + SEPID uint64 `url:"sepId"` + + // Pool to use if sepId is set, can be also empty if needed to be chosen by system + // Required: true + Pool string `url:"pool"` + + // Network type + // Should be one of: + // - VINS + // - EXTNET + // - NONE + // Required: false + NetType string `url:"netType,omitempty"` + + // Network ID for connect to, + // for EXTNET - external network ID, + // for VINS - VINS ID, + // when network type is not "NONE" + // Required: false + NetID uint64 `url:"netId,omitempty"` + + // IP address to assign to this VM when connecting to the specified network + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // Text description of this VM + // Required: false + Description string `url:"desc,omitempty"` } -func (krq CreateBlankRequest) Validate() error { +func (krq CreateBlankRequest) validate() error { if krq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -37,7 +79,7 @@ func (krq CreateBlankRequest) Validate() error { if krq.BootDisk == 0 { return errors.New("validation-error: field BootDisk must be set") } - if krq.SepID == 0 { + if krq.SEPID == 0 { return errors.New("validation-error: field SepID must be set") } if krq.Pool == "" { @@ -47,8 +89,9 @@ func (krq CreateBlankRequest) Validate() error { return nil } +// CreateBlank creates KVM x86 VM from scratch func (k KVMX86) CreateBlank(ctx context.Context, req CreateBlankRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } @@ -67,4 +110,4 @@ func (k KVMX86) CreateBlank(ctx context.Context, req CreateBlankRequest) (uint64 return result, nil -} \ No newline at end of file +} diff --git a/pkg/cloudbroker/kvmx86/kvmx86.go b/pkg/cloudbroker/kvmx86/kvmx86.go index 1fa447a..b19ec30 100644 --- a/pkg/cloudbroker/kvmx86/kvmx86.go +++ b/pkg/cloudbroker/kvmx86/kvmx86.go @@ -1,11 +1,14 @@ +// API to manage KVM x86 compute instances (x86 VMs) package kvmx86 import "github.com/rudecs/decort-sdk/interfaces" +// Structure for creating request to KVMX86 type KVMX86 struct { client interfaces.Caller } +// Builder for KVMX86 endpoints func New(client interfaces.Caller) *KVMX86 { return &KVMX86{ client: client, diff --git a/pkg/cloudbroker/kvmx86/mass_create.go b/pkg/cloudbroker/kvmx86/mass_create.go index 144aed4..5743c08 100644 --- a/pkg/cloudbroker/kvmx86/mass_create.go +++ b/pkg/cloudbroker/kvmx86/mass_create.go @@ -7,26 +7,83 @@ import ( "net/http" ) +// Request struct for mass create KVM x86 type MassCreateRequest struct { - RGID uint64 `url:"rgId"` - Name string `url:"name"` - Count uint64 `url:"count"` - CPU uint64 `url:"cpu"` - RAM uint64 `url:"ram"` - ImageID uint64 `url:"imageId"` - BootDisk uint64 `url:"bootDisk,omitempty"` - SepID uint64 `url:"sepId,omitempty"` - Pool string `url:"pool,omitempty"` - NetType string `url:"netType,omitempty"` - NetID uint64 `url:"netId,omitempty"` - IPAddr string `url:"ipAddr,omitempty"` + // ID of the resource group, which will own this VM + // Required: true + RGID uint64 `url:"rgId"` + + // Name of this VM. + // Must be unique among all VMs (including those in DELETED state) in target resource group + // Required: true + Name string `url:"name"` + + // Number of VMs + // Required: true + Count uint64 `url:"count"` + + // Number CPUs to allocate to this VM + // Required: true + CPU uint64 `url:"cpu"` + + // Volume of RAM in MB to allocate to this VM + // Required: true + RAM uint64 `url:"ram"` + + // Image ID + // Required: true + ImageID uint64 `url:"imageId"` + + // Size of the boot disk in GB + // Required: true + BootDisk uint64 `url:"bootDisk"` + + // ID of SEP to create boot disk on. + // Uses images SEP ID if not set + // Required: true + SEPID uint64 `url:"sepId"` + + // Pool to use if SEP ID is set, can be also empty if needed to be chosen by system + // Required: true + Pool string `url:"pool"` + + // Network type + // Should be one of: + // - VINS + // - EXTNET + // - NONE + // Required: false + NetType string `url:"netType,omitempty"` + + // Network ID for connect to, + // for EXTNET - external network ID, + // for VINS - VINS ID, + // when network type is not "NONE" + // Required: false + NetID uint64 `url:"netId,omitempty"` + + // IP address to assign to this VM when connecting to the specified network + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // User data + // Required: false UserData string `url:"userdata,omitempty"` - Desc string `url:"desc,omitempty"` - Start bool `url:"start,omitempty"` - Reason string `url:"reason,omitempty"` + + // Text description of this VM + // Required: false + Description string `url:"desc,omitempty"` + + // Start after create of not + // Required: false + Start bool `url:"start,omitempty"` + + // Reason to action + // Required: false + Reason string `url:"reason,omitempty"` } -func (krq MassCreateRequest) Validate() error { +func (krq MassCreateRequest) validate() error { if krq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -49,8 +106,9 @@ func (krq MassCreateRequest) Validate() error { return nil } +// MassCreate creates KVM x86 computes based on specified OS image func (k KVMX86) MassCreate(ctx context.Context, req MassCreateRequest) ([]uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return nil, err } diff --git a/pkg/cloudbroker/lb.go b/pkg/cloudbroker/lb.go index 74bd3a2..3f811c3 100644 --- a/pkg/cloudbroker/lb.go +++ b/pkg/cloudbroker/lb.go @@ -1,7 +1,8 @@ package cloudbroker -import "github.com/rudecs/decort-sdk/pkg/cloudapi/lb" +import "github.com/rudecs/decort-sdk/pkg/cloudbroker/lb" +// Accessing the LB method group func (cb *CloudBroker) LB() *lb.LB { return lb.New(cb.client) } diff --git a/pkg/cloudbroker/lb/backend_create.go b/pkg/cloudbroker/lb/backend_create.go new file mode 100644 index 0000000..70f71ae --- /dev/null +++ b/pkg/cloudbroker/lb/backend_create.go @@ -0,0 +1,106 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" +) + +// Request struct for create backend +type BackendCreateRequest struct { + // ID of the load balancer instance to backendCreate + // Required: true + LBID uint64 `url:"lbId"` + + // Must be unique among all backends of this load balancer - name of the new backend to create + // Required: true + BackendName string `url:"backendName"` + + // Algorithm + // Should be one of: + // - roundrobin + // - static-rr + // - leastconn + // Required: false + Algorithm string `url:"algorithm,omitempty"` + + // Interval in milliseconds between two consecutive availability + // checks of the server that is considered available + // Required: false + Inter uint64 `url:"inter,omitempty"` + + // Interval in milliseconds between two consecutive checks to + // restore the availability of a server that is currently considered unavailable + // Required: false + DownInter uint64 `url:"downinter,omitempty"` + + // Number of checks that the server must pass in order to get the available status + // and be included in the balancing scheme again + // Required: false + Rise uint64 `url:"rise,omitempty"` + + // Number of consecutive failed availability checks, + // after which the previously considered available server receives the status of + // unavailable and is temporarily excluded from the balancing scheme + // Required: false + Fall uint64 `url:"fall,omitempty"` + + // Interval in milliseconds from the moment the server receives the available status, + // after which the number of actually allowed connections to this server will be returned to 100% of the set limit + // Required: false + SlowStart uint64 `url:"slowstart,omitempty"` + + // Limit of simultaneous connections to the server. When this limit is reached, + // the server is temporarily excluded from the balancing scheme + // Required: false + MaxConn uint64 `url:"maxconn,omitempty"` + + // Limit of connections waiting in the queue. + // When this limit is reached, all subsequent connections will be forwarded to other servers + // Required: false + MaxQueue uint64 `url:"maxqueue,omitempty"` + + // Server weight for use in weight balancing algorithms + // Required: false + Weight uint64 `url:"weight,omitempty"` +} + +func (lbrq BackendCreateRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + if lbrq.BackendName == "" { + return errors.New("validation-error: field BackendName must be set") + } + validate := validators.StringInSlice(lbrq.Algorithm, []string{"roundrobin", "static-rr", "leastconn"}) + if !validate { + return errors.New("validation-error: field Algorithm must be one of roundrobin, static-rr, leastconn") + } + + return nil +} + +// BackendCreate creates new backend on the specified load balancer +func (lb LB) BackendCreate(ctx context.Context, req BackendCreateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/backendCreate" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/backend_delete.go b/pkg/cloudbroker/lb/backend_delete.go new file mode 100644 index 0000000..908dbbc --- /dev/null +++ b/pkg/cloudbroker/lb/backend_delete.go @@ -0,0 +1,53 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete backend +type BackendDeleteRequest struct { + // ID of the load balancer instance to BackendDelete + // Required: true + LBID uint64 `url:"lbId"` + + // Cannot be emtpy string - name of the backend to delete + // Required: true + BackendName string `url:"backendName"` +} + +func (lbrq BackendDeleteRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + if lbrq.BackendName == "" { + return errors.New("validation-error: field BackendName must be set") + } + + return nil +} + +// BackendDelete deletes backend from the specified load balancer. +// Warning: you cannot undo this action! +func (lb LB) BackendDelete(ctx context.Context, req BackendDeleteRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/backendDelete" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/backend_server_add.go b/pkg/cloudbroker/lb/backend_server_add.go new file mode 100644 index 0000000..89e3de9 --- /dev/null +++ b/pkg/cloudbroker/lb/backend_server_add.go @@ -0,0 +1,114 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for add server definition to the backend +type BackendServerAddRequest struct { + // ID of the load balancer instance to BackendServerAdd + // Required: true + LBID uint64 `url:"lbId"` + + // Must match one of the existing backens - name of the backend to add servers to + // Required: true + BackendName string `url:"backendName"` + + // Must be unique among all servers defined for this backend - name of the server definition to add + // Required: true + ServerName string `url:"serverName"` + + // IP address of the server + // Required: true + Address string `url:"address"` + + // Port number on the server + // Required: true + Port uint64 `url:"port"` + + // Set to disabled if this server should be used regardless of its state + // Required: false + Check string `url:"check,omitempty"` + + // Interval in milliseconds between two consecutive availability checks of the server that is considered available + // Required: false + Inter uint64 `url:"inter,omitempty"` + + // Interval in milliseconds between two consecutive checks to restore + // the availability of a server that is currently considered unavailable + // Required: false + DownInter uint64 `url:"downinter,omitempty"` + + // Number of checks that the server must pass in order to get + // the available status and be included in the balancing scheme again + // Required: false + Rise uint64 `url:"rise,omitempty"` + + // Number of consecutive failed availability checks, + // after which the previously considered available server receives the status of unavailable and + // is temporarily excluded from the balancing scheme + // Required: false + Fall uint64 `url:"fall,omitempty"` + + // Interval in milliseconds from the moment the server receives the available status, + // after which the number of actually allowed connections to this server will be returned to 100% of the set limit + // Required: false + SlowStart uint64 `url:"slowstart,omitempty"` + + // Limit of simultaneous connections to the server. When this limit is reached, the server is temporarily excluded from the balancing scheme + // Required: false + MaxConn uint64 `url:"maxconn,omitempty"` + + // Limit of connections waiting in the queue. When this limit is reached, all subsequent connections will be forwarded to other servers + // Required: false + MaxQueue uint64 `url:"maxqueue,omitempty"` + + // Server weight for use in weight balancing algorithms + // Required: false + Weight uint64 `url:"weight,omitempty"` +} + +func (lbrq BackendServerAddRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + if lbrq.BackendName == "" { + return errors.New("validation-error: field BackendName must be set") + } + if lbrq.ServerName == "" { + return errors.New("validation-error: field ServerName must be set") + } + if lbrq.Address == "" { + return errors.New("validation-error: field Address must be set") + } + if lbrq.Port == 0 { + return errors.New("validation-error: field Port must be set") + } + + return nil +} + +// BackendServerAdd adds server definition to the backend on the specified load balancer +func (lb LB) BackendServerAdd(ctx context.Context, req BackendServerAddRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/backendServerAdd" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/backend_server_delete.go b/pkg/cloudbroker/lb/backend_server_delete.go new file mode 100644 index 0000000..567c7f3 --- /dev/null +++ b/pkg/cloudbroker/lb/backend_server_delete.go @@ -0,0 +1,62 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete server definition +type BackendServerDeleteRequest struct { + // ID of the load balancer instance to BackendServerDelete + // Required: true + LBID uint64 `url:"lbId"` + + // Must match one of the existing backens - name of the backend to add servers to + // Required: true + BackendName string `url:"backendName"` + + // Must be unique among all servers defined for this backend - name of the server definition to add + // Required: true + ServerName string `url:"serverName"` +} + +func (lbrq BackendServerDeleteRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + + if lbrq.BackendName == "" { + return errors.New("validation-error: field BackendName must be set") + } + + if lbrq.ServerName == "" { + return errors.New("validation-error: field ServerName must be set") + } + + return nil +} + +// BackendServerDelete deletes server definition from the backend on the specified load balancer. +// Warning: you cannot undo this action! +func (lb LB) BackendServerDelete(ctx context.Context, req BackendServerDeleteRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/backendServerDelete" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/backend_server_update.go b/pkg/cloudbroker/lb/backend_server_update.go new file mode 100644 index 0000000..d5ef4b6 --- /dev/null +++ b/pkg/cloudbroker/lb/backend_server_update.go @@ -0,0 +1,114 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for update server +type BackendServerUpdateRequest struct { + // ID of the load balancer instance to BackendServerAdd + // Required: true + LBID uint64 `url:"lbId"` + + // Must match one of the existing backens - name of the backend to add servers to + // Required: true + BackendName string `url:"backendName"` + + // Must be unique among all servers defined for this backend - name of the server definition to add + // Required: true + ServerName string `url:"serverName"` + + // IP address of the server + // Required: true + Address string `url:"address"` + + // Port number on the server + // Required: true + Port uint64 `url:"port"` + + // Set to disabled if this server should be used regardless of its state + // Required: false + Check string `url:"check,omitempty"` + + // Interval in milliseconds between two consecutive availability checks of the server that is considered available + // Required: false + Inter uint64 `url:"inter,omitempty"` + + // Interval in milliseconds between two consecutive checks to restore + // the availability of a server that is currently considered unavailable + // Required: false + DownInter uint64 `url:"downinter,omitempty"` + + // Number of checks that the server must pass in order to get + // the available status and be included in the balancing scheme again + // Required: false + Rise uint64 `url:"rise,omitempty"` + + // Number of consecutive failed availability checks, + // after which the previously considered available server receives the status of unavailable and + // is temporarily excluded from the balancing scheme + // Required: false + Fall uint64 `url:"fall,omitempty"` + + // Interval in milliseconds from the moment the server receives the available status, + // after which the number of actually allowed connections to this server will be returned to 100% of the set limit + // Required: false + SlowStart uint64 `url:"slowstart,omitempty"` + + // Limit of simultaneous connections to the server. When this limit is reached, the server is temporarily excluded from the balancing scheme + // Required: false + MaxConn uint64 `url:"maxconn,omitempty"` + + // Limit of connections waiting in the queue. When this limit is reached, all subsequent connections will be forwarded to other servers + // Required: false + MaxQueue uint64 `url:"maxqueue,omitempty"` + + // Server weight for use in weight balancing algorithms + // Required: false + Weight uint64 `url:"weight,omitempty"` +} + +func (lbrq BackendServerUpdateRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + if lbrq.BackendName == "" { + return errors.New("validation-error: field BackendName must be set") + } + if lbrq.ServerName == "" { + return errors.New("validation-error: field ServerName must be set") + } + if lbrq.Address == "" { + return errors.New("validation-error: field Address must be set") + } + if lbrq.Port == 0 { + return errors.New("validation-error: field Port must be set") + } + + return nil +} + +// BackendServerUpdate updates server definition on the backend of load balancer +func (lb LB) BackendServerUpdate(ctx context.Context, req BackendServerUpdateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/backendServerUpdate" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/backend_update.go b/pkg/cloudbroker/lb/backend_update.go new file mode 100644 index 0000000..2fa3d90 --- /dev/null +++ b/pkg/cloudbroker/lb/backend_update.go @@ -0,0 +1,100 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for update backend +type BackendUpdateRequest struct { + // ID of the load balancer instance to backendCreate + // Required: true + LBID uint64 `url:"lbId"` + + // Must be unique among all backends of this load balancer - name of the new backend to create + // Required: true + BackendName string `url:"backendName"` + + // Algorithm + // Should be one of: + // - roundrobin + // - static-rr + // - leastconn + // Required: false + Algorithm string `url:"algorithm,omitempty"` + + // Interval in milliseconds between two consecutive availability + // checks of the server that is considered available + // Required: false + Inter uint64 `url:"inter,omitempty"` + + // Interval in milliseconds between two consecutive checks to + // restore the availability of a server that is currently considered unavailable + // Required: false + DownInter uint64 `url:"downinter,omitempty"` + + // Number of checks that the server must pass in order to get the available status + // and be included in the balancing scheme again + // Required: false + Rise uint64 `url:"rise,omitempty"` + + // Number of consecutive failed availability checks, + // after which the previously considered available server receives the status of + // unavailable and is temporarily excluded from the balancing scheme + // Required: false + Fall uint64 `url:"fall,omitempty"` + + // Interval in milliseconds from the moment the server receives the available status, + // after which the number of actually allowed connections to this server will be returned to 100% of the set limit + // Required: false + SlowStart uint64 `url:"slowstart,omitempty"` + + // Limit of simultaneous connections to the server. When this limit is reached, + // the server is temporarily excluded from the balancing scheme + // Required: false + MaxConn uint64 `url:"maxconn,omitempty"` + + // Limit of connections waiting in the queue. + // When this limit is reached, all subsequent connections will be forwarded to other servers + // Required: false + MaxQueue uint64 `url:"maxqueue,omitempty"` + + // Server weight for use in weight balancing algorithms + // Required: false + Weight uint64 `url:"weight,omitempty"` +} + +func (lbrq BackendUpdateRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + if lbrq.BackendName == "" { + return errors.New("validation-error: field BackendName must be set") + } + + return nil +} + +// BackendUpdate updates existing backend on the specified load balancer. Note that backend name cannot be changed +func (lb LB) BackendUpdate(ctx context.Context, req BackendUpdateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/backendUpdate" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/config_reset.go b/pkg/cloudbroker/lb/config_reset.go new file mode 100644 index 0000000..3b71d7f --- /dev/null +++ b/pkg/cloudbroker/lb/config_reset.go @@ -0,0 +1,46 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for reset config +type ConfigResetRequest struct { + // ID of the load balancer instance to ConfigReset + // Required: true + LBID uint64 `url:"lbId"` +} + +func (lbrq ConfigResetRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + + return nil +} + +// ConfigReset reset current software configuration of the specified load balancer. +// Warning: this action cannot be undone! +func (lb LB) ConfigReset(ctx context.Context, req ConfigResetRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/configReset" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/create.go b/pkg/cloudbroker/lb/create.go new file mode 100644 index 0000000..645b5e7 --- /dev/null +++ b/pkg/cloudbroker/lb/create.go @@ -0,0 +1,79 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for create load balancer +type CreateRequest struct { + // ID of the resource group where this load balancer instance will be located + // Required: true + RGID uint64 `url:"rgId"` + + // Name of the load balancer. + // Must be unique among all load balancers in this resource group + // Required: true + Name string `url:"name"` + + // OS image ID to create load balancer from + // Required: false + ImageID uint64 `url:"imageId,omitempty"` + + // External network to connect this load balancer to + // Required: true + ExtNetID uint64 `url:"extnetId"` + + // Internal network (VINS) to connect this load balancer to + // Required: true + VINSID uint64 `url:"vinsId"` + + // Start now Load balancer + // Required: false + Start bool `url:"start"` + + // Text description of this load balancer + // Required: false + Description string `url:"desc,omitempty"` +} + +func (lbrq CreateRequest) validate() error { + if lbrq.RGID == 0 { + return errors.New("validation-error: field RGID must be set") + } + if lbrq.Name == "" { + return errors.New("validation-error: field Name must be set") + } + if lbrq.ExtNetID == 0 { + return errors.New("validation-error: field ExtNetID must be set") + } + if lbrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + + return nil +} + +// Create method will create a new load balancer instance +func (lb LB) Create(ctx context.Context, req CreateRequest) (uint64, error) { + err := req.validate() + if err != nil { + return 0, err + } + + url := "/cloudbroker/lb/create" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/delete.go b/pkg/cloudbroker/lb/delete.go new file mode 100644 index 0000000..b6beab9 --- /dev/null +++ b/pkg/cloudbroker/lb/delete.go @@ -0,0 +1,49 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete load balancer +type DeleteRequest struct { + // ID of the load balancer instance to delete + // Required: true + LBID uint64 `url:"lbId"` + + // Set to true to delete load balancer immediately bypassing recycle bin + // Required: false + Permanently bool `url:"permanently,omitempty"` +} + +func (lbrq DeleteRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + + return nil +} + +// Delete deletes specified load balancer +func (lb LB) Delete(ctx context.Context, req DeleteRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/delete" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/disable.go b/pkg/cloudbroker/lb/disable.go new file mode 100644 index 0000000..bec084a --- /dev/null +++ b/pkg/cloudbroker/lb/disable.go @@ -0,0 +1,45 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for disable load balancer +type DisableRequest struct { + // ID of the load balancer instance to disable + // Required: true + LBID uint64 `url:"lbId"` +} + +func (lbrq DisableRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + + return nil +} + +// Disable disables specified load balancer instance +func (lb LB) Disable(ctx context.Context, req DisableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/disable" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/enable.go b/pkg/cloudbroker/lb/enable.go new file mode 100644 index 0000000..9763639 --- /dev/null +++ b/pkg/cloudbroker/lb/enable.go @@ -0,0 +1,45 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for enable load balancer +type EnableRequest struct { + // ID of the load balancer instance to enable + // Required: true + LBID uint64 `url:"lbId"` +} + +func (lbrq EnableRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + + return nil +} + +// Enable enables specified load balancer instance +func (lb LB) Enable(ctx context.Context, req EnableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/enable" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/frontend_bind.go b/pkg/cloudbroker/lb/frontend_bind.go new file mode 100644 index 0000000..6f3e5a5 --- /dev/null +++ b/pkg/cloudbroker/lb/frontend_bind.go @@ -0,0 +1,76 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for frontend bind +type FrontendBindRequest struct { + // ID of the load balancer instance to FrontendBind + // Required: true + LBID uint64 `url:"lbId"` + + // Name of the frontend to update + // Required: true + FrontendName string `url:"frontendName"` + + // Name of the binding to update + // Required: true + BindingName string `url:"bindingName"` + + // If specified must be within the IP range of either Ext Net or ViNS, + // where this load balancer is connected - new IP address to use for this binding. + // If omitted, current IP address is retained + // Required: false + BindingAddress string `url:"bindingAddress,omitempty"` + + // New port number to use for this binding. + // If omitted, current port number is retained + // Required: false + BindingPort uint64 `url:"bindingPort,omitempty"` +} + +func (lbrq FrontendBindRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + if lbrq.FrontendName == "" { + return errors.New("validation-error: field FrontendName must be set") + } + if lbrq.BindingName == "" { + return errors.New("validation-error: field BindingName must be set") + } + if lbrq.BindingAddress == "" { + return errors.New("validation-error: field BindingAddress must be set") + } + if lbrq.BindingPort == 0 { + return errors.New("validation-error: field BindingPort must be set") + } + + return nil +} + +// FrontendBind bind frontend from specified load balancer instance +func (lb LB) FrontendBind(ctx context.Context, req FrontendBindRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/frontendBind" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/frontend_bind_delete.go b/pkg/cloudbroker/lb/frontend_bind_delete.go new file mode 100644 index 0000000..c2217ec --- /dev/null +++ b/pkg/cloudbroker/lb/frontend_bind_delete.go @@ -0,0 +1,59 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete bind +type FrontendBindDeleteRequest struct { + // ID of the load balancer instance to FrontendBindDelete + // Required: true + LBID uint64 `url:"lbId"` + + // Name of the frontend to delete + // Required: true + FrontendName string `url:"frontendName"` + + // Name of the binding to delete + // Required: true + BindingName string `url:"bindingName"` +} + +func (lbrq FrontendBindDeleteRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + if lbrq.FrontendName == "" { + return errors.New("validation-error: field FrontendName must be set") + } + if lbrq.BindingName == "" { + return errors.New("validation-error: field BindingName must be set") + } + + return nil +} + +// FrontendBindDelete deletes binding from the specified load balancer frontend +func (lb LB) FrontendBindDelete(ctx context.Context, req FrontendBindDeleteRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/frontendBindDelete" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/frontend_binding_update.go b/pkg/cloudbroker/lb/frontend_binding_update.go new file mode 100644 index 0000000..64d7830 --- /dev/null +++ b/pkg/cloudbroker/lb/frontend_binding_update.go @@ -0,0 +1,76 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for update binding +type FrontendBindUpdateRequest struct { + // ID of the load balancer instance to FrontendBindUpdate + // Required: true + LBID uint64 `url:"lbId"` + + // Name of the frontend to update + // Required: true + FrontendName string `url:"frontendName"` + + // Name of the binding to update + // Required: true + BindingName string `url:"bindingName"` + + // If specified must be within the IP range of either Ext Net or ViNS, + // where this load balancer is connected - new IP address to use for this binding. + // If omitted, current IP address is retained + // Required: false + BindingAddress string `url:"bindingAddress,omitempty"` + + // New port number to use for this binding. + // If omitted, current port number is retained + // Required: false + BindingPort uint64 `url:"bindingPort,omitempty"` +} + +func (lbrq FrontendBindUpdateRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + if lbrq.FrontendName == "" { + return errors.New("validation-error: field FrontendName must be set") + } + if lbrq.BindingName == "" { + return errors.New("validation-error: field BindingName must be set") + } + if lbrq.BindingAddress == "" { + return errors.New("validation-error: field BindingAddress must be set") + } + if lbrq.BindingPort == 0 { + return errors.New("validation-error: field BindingPort must be set") + } + + return nil +} + +// FrontendBindUpdate updates binding for the specified load balancer frontend +func (lb LB) FrontendBindUpdate(ctx context.Context, req FrontendBindUpdateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/frontendBindingUpdate" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/frontend_create.go b/pkg/cloudbroker/lb/frontend_create.go new file mode 100644 index 0000000..733054a --- /dev/null +++ b/pkg/cloudbroker/lb/frontend_create.go @@ -0,0 +1,61 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for create frontend +type FrontendCreateRequest struct { + // ID of the load balancer instance to FrontendCreate + // Required: true + LBID uint64 `url:"lbId"` + + // Must be unique among all frontends of + // this load balancer - name of the new frontend to create + // Required: true + FrontendName string `url:"frontendName"` + + // Should be one of the backends existing on + // this load balancer - name of the backend to use + // Required: true + BackendName string `url:"backendName"` +} + +func (lbrq FrontendCreateRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + if lbrq.FrontendName == "" { + return errors.New("validation-error: field FrontendName must be set") + } + if lbrq.BackendName == "" { + return errors.New("validation-error: field BackendName must be set") + } + + return nil +} + +// FrontendCreate creates new frontend on the specified load balancer +func (l LB) FrontendCreate(ctx context.Context, req FrontendCreateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/frontendCreate" + + res, err := l.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/frontend_delete.go b/pkg/cloudbroker/lb/frontend_delete.go new file mode 100644 index 0000000..0302853 --- /dev/null +++ b/pkg/cloudbroker/lb/frontend_delete.go @@ -0,0 +1,53 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete frontend +type FrontendDeleteRequest struct { + // ID of the load balancer instance to FrontendDelete + // Required: true + LBID uint64 `url:"lbId"` + + // Name of the frontend to delete + // Required: true + FrontendName string `url:"frontendName"` +} + +func (lbrq FrontendDeleteRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + if lbrq.FrontendName == "" { + return errors.New("validation-error: field FrontendName must be set") + } + + return nil +} + +// FrontendDelete deletes frontend from the specified load balancer. +// Warning: you cannot undo this action! +func (lb LB) FrontendDelete(ctx context.Context, req FrontendDeleteRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/frontendDelete" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/get.go b/pkg/cloudbroker/lb/get.go new file mode 100644 index 0000000..1cc9099 --- /dev/null +++ b/pkg/cloudbroker/lb/get.go @@ -0,0 +1,47 @@ +package lb + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get detailed information about load balancer +type GetRequest struct { + // ID of the load balancer to get details for + // Required: true + LBID uint64 `url:"lbId"` +} + +func (lbrq GetRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + + return nil +} + +// Get gets detailed information about load balancer +func (lb LB) Get(ctx context.Context, req GetRequest) (*RecordLB, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/lb/get" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + info := RecordLB{} + err = json.Unmarshal(res, &info) + if err != nil { + return nil, err + } + + return &info, nil + +} diff --git a/pkg/cloudbroker/lb/lb.go b/pkg/cloudbroker/lb/lb.go new file mode 100644 index 0000000..33fc220 --- /dev/null +++ b/pkg/cloudbroker/lb/lb.go @@ -0,0 +1,16 @@ +// API to manage load balancer instance +package lb + +import "github.com/rudecs/decort-sdk/interfaces" + +// Structure for creating request to load balancer +type LB struct { + client interfaces.Caller +} + +// Builder for load balancer +func New(client interfaces.Caller) *LB { + return &LB{ + client: client, + } +} diff --git a/pkg/cloudbroker/lb/list.go b/pkg/cloudbroker/lb/list.go new file mode 100644 index 0000000..a6609d9 --- /dev/null +++ b/pkg/cloudbroker/lb/list.go @@ -0,0 +1,42 @@ +package lb + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get list of load balancers +type ListRequest struct { + // Included deleted load balancers + // Required: false + IncludeDeleted bool `url:"includedeleted,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} + +// List gets list all load balancers +func (lb LB) List(ctx context.Context, req ListRequest) (ListLB, error) { + url := "/cloudbroker/lb/list" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListLB{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil + +} diff --git a/pkg/cloudbroker/lb/list_deleted.go b/pkg/cloudbroker/lb/list_deleted.go new file mode 100644 index 0000000..d7e9a32 --- /dev/null +++ b/pkg/cloudbroker/lb/list_deleted.go @@ -0,0 +1,38 @@ +package lb + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get list of deleted load balancers +type ListDeletedRequest struct { + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: true + Size uint64 `url:"size,omitempty"` +} + +// ListDeleted gets list of deleted load balancers +func (lb LB) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListLB, error) { + url := "/cloudbroker/lb/listDeleted" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListLB{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil + +} diff --git a/pkg/cloudbroker/lb/models.go b/pkg/cloudbroker/lb/models.go new file mode 100644 index 0000000..456b6a6 --- /dev/null +++ b/pkg/cloudbroker/lb/models.go @@ -0,0 +1,227 @@ +package lb + +// Server settings +type ServerSettings struct { + // Inter + Inter uint64 `json:"inter"` + + // GUID + GUID string `json:"guid"` + + // DownInter + DownInter uint64 `json:"downinter"` + + // Rise + Rise uint64 `json:"rise"` + + // Fall + Fall uint64 `json:"fall"` + + // SlowStart + SlowStart uint64 `json:"slowstart"` + + // Max connections + MaxConn uint64 `json:"maxconn"` + + // Max queue + MaxQueue uint64 `json:"maxqueue"` + + // Weight + Weight uint64 `json:"weight"` +} + +// Main information about server +type ItemServer struct { + + // Address + Address string `json:"address"` + + // Check + Check string `json:"check"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` + + // Port + Port uint64 `json:"port"` + + // Server settings + ServerSettings ServerSettings `json:"serverSettings"` +} + +// List of servers +type ListServers []ItemServer + +// Main information about backend +type ItemBackend struct { + // Algorithm + Algorithm string `json:"algorithm"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` + + // Server settings + ServerDefaultSettings ServerSettings `json:"serverDefaultSettings"` + + // List of servers + Servers ListServers `json:"servers"` +} + +// List of backends +type ListBackends []ItemBackend + +// Main information about frontend +type ItemFrontend struct { + // Backend + Backend string `json:"backend"` + + // List of bindings + Bindings ListBindings `json:"bindings"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` +} + +// List of frontends +type ListFrontends []ItemFrontend + +// Main information about bindings +type ItemBinding struct { + // Address + Address string `json:"address"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` + + // Port + Port uint64 `json:"port"` +} + +// List of bindings +type ListBindings []ItemBinding + +// Main information about node +type Node struct { + // Backend IP + BackendIP string `json:"backendIp"` + + // Compute ID + ComputeID uint64 `json:"computeId"` + + // Frontend IP + FrontendIP string `json:"frontendIp"` + + // GUID + GUID string `json:"guid"` + + // MGMTIP + MGMTIP string `json:"mgmtIp"` + + // Network ID + NetworkID uint64 `json:"networkId"` +} + +// List of load balancers +type ListLB []RecordLB + +// Detailed information about load balancer +type RecordLB struct { + // HAMode + HAMode bool `json:"HAmode"` + + // CKey + CKey string `json:"_ckey"` + + // Meta + Meta []interface{} `json:"_meta"` + + // Access Control List + ACL []interface{} `json:"acl"` + + // List of load balancer backends + Backends ListBackends `json:"backends"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // DPAPI password + DPAPIPassword string `json:"dpApiPassword"` + + // DPAPI user + DPAPIUser string `json:"dpApiUser"` + + // External network ID + ExtNetID uint64 `json:"extnetId"` + + // List of load balancer frontends + Frontends ListFrontends `json:"frontends"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Image ID + ImageID uint64 `json:"imageId"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Primary node + PrimaryNode Node `json:"primaryNode"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Secondary node + SecondaryNode Node `json:"secondaryNode"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // VINS ID + VINSID uint64 `json:"vinsId"` +} diff --git a/pkg/cloudbroker/lb/restart.go b/pkg/cloudbroker/lb/restart.go new file mode 100644 index 0000000..bd15a9c --- /dev/null +++ b/pkg/cloudbroker/lb/restart.go @@ -0,0 +1,45 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for restart load balancer +type RestartRequest struct { + // ID of the load balancer instance to restart + // Required: true + LBID uint64 `url:"lbId"` +} + +func (lbrq RestartRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + + return nil +} + +// Restart restarts specified load balancer instance +func (lb LB) Restart(ctx context.Context, req RestartRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/restart" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/restore.go b/pkg/cloudbroker/lb/restore.go new file mode 100644 index 0000000..5bb36b9 --- /dev/null +++ b/pkg/cloudbroker/lb/restore.go @@ -0,0 +1,45 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for restore load balancer +type RestoreRequest struct { + // ID of the load balancer instance to restore + // Required: true + LBID uint64 `url:"lbId"` +} + +func (lbrq RestoreRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + + return nil +} + +// Restore restore load balancer from recycle bin +func (lb LB) Restore(ctx context.Context, req RestoreRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/restore" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/start.go b/pkg/cloudbroker/lb/start.go new file mode 100644 index 0000000..ace0d0e --- /dev/null +++ b/pkg/cloudbroker/lb/start.go @@ -0,0 +1,45 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for start load balancer +type StartRequest struct { + // ID of the LB instance to start + // Required: true + LBID uint64 `url:"lbId"` +} + +func (lbrq StartRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + + return nil +} + +// Start starts specified load balancer instance +func (lb LB) Start(ctx context.Context, req StartRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/start" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/stop.go b/pkg/cloudbroker/lb/stop.go new file mode 100644 index 0000000..7d0fed7 --- /dev/null +++ b/pkg/cloudbroker/lb/stop.go @@ -0,0 +1,45 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for stop load balancer +type StopRequest struct { + // ID of the LB instance to stop + // Required: true + LBID uint64 `url:"lbId"` +} + +func (lbrq StopRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + + return nil +} + +// Stop stops specified load balancer instance +func (lb LB) Stop(ctx context.Context, req StopRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/stop" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/lb/update.go b/pkg/cloudbroker/lb/update.go new file mode 100644 index 0000000..30c9454 --- /dev/null +++ b/pkg/cloudbroker/lb/update.go @@ -0,0 +1,53 @@ +package lb + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for update load balancer +type UpdateRequest struct { + // ID of the load balancer to update + // Required: true + LBID uint64 `url:"lbId"` + + // New description of this load balancer. + // If omitted, current description is retained + // Required: true + Description string `url:"desc"` +} + +func (lbrq UpdateRequest) validate() error { + if lbrq.LBID == 0 { + return errors.New("validation-error: field LBID must be set") + } + if lbrq.Description == "" { + return errors.New("validation-error: field Description must be set") + } + + return nil +} + +// Update updates some of load balancer attributes +func (lb LB) Update(ctx context.Context, req UpdateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/lb/update" + + res, err := lb.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/locatons.go b/pkg/cloudbroker/locatons.go deleted file mode 100644 index 426a248..0000000 --- a/pkg/cloudbroker/locatons.go +++ /dev/null @@ -1,7 +0,0 @@ -package cloudbroker - -import "github.com/rudecs/decort-sdk/pkg/cloudapi/locations" - -func (cb *CloudBroker) Locations() *locations.Locations { - return locations.New(cb.client) -} diff --git a/pkg/cloudbroker/rg.go b/pkg/cloudbroker/rg.go index ff4a672..2198f03 100644 --- a/pkg/cloudbroker/rg.go +++ b/pkg/cloudbroker/rg.go @@ -2,6 +2,7 @@ package cloudbroker import "github.com/rudecs/decort-sdk/pkg/cloudbroker/rg" +// Accessing the RG method group func (cb *CloudBroker) RG() *rg.RG { return rg.New(cb.client) } diff --git a/pkg/cloudbroker/rg/access_grant.go b/pkg/cloudbroker/rg/access_grant.go index f384453..0c485ea 100644 --- a/pkg/cloudbroker/rg/access_grant.go +++ b/pkg/cloudbroker/rg/access_grant.go @@ -3,27 +3,42 @@ package rg import ( "context" "errors" - "github.com/rudecs/decort-sdk/internal/validators" "net/http" "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for grant access to resource group type AccessGrantRequest struct { - RGID uint64 `url:"rgId"` - User string `url:"user"` - Right string `url:"right"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // User or group name to grant access + // Required: true + User string `url:"user"` + + // Access rights to set, + // Should be one of: + // - "R" + // - "RCX" + // - "ARCXDU" + // Required: true + Right string `url:"right"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq AccessGrantRequest) Validate() error { +func (rgrq AccessGrantRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } - if rgrq.User == "" { return errors.New("validation-error: field User must be set") } - validate := validators.StringInSlice(rgrq.Right, []string{"R", "RCX", "ARCXDU"}) if !validate { return errors.New("field Right can only be one of 'R', 'RCX' or 'ARCXDU'") @@ -32,8 +47,9 @@ func (rgrq AccessGrantRequest) Validate() error { return nil } +// AccessGrant grants user or group access to the resource group as specified func (r RG) AccessGrant(ctx context.Context, req AccessGrantRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/rg/access_revoke.go b/pkg/cloudbroker/rg/access_revoke.go index 6a4b020..ee9c825 100644 --- a/pkg/cloudbroker/rg/access_revoke.go +++ b/pkg/cloudbroker/rg/access_revoke.go @@ -7,17 +7,25 @@ import ( "strconv" ) +// Request struct for revoke access type AccessRevokeRequest struct { - RGID uint64 `url:"rgId"` - User string `url:"user"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // User or group name to revoke access + // Required: true + User string `url:"user"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq AccessRevokeRequest) Validate() error { +func (rgrq AccessRevokeRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } - if rgrq.User == "" { return errors.New("validation-error: field User must be set") } @@ -25,8 +33,10 @@ func (rgrq AccessRevokeRequest) Validate() error { return nil } +// AccessRevoke revokes specified user or group access from the resource group func (r RG) AccessRevoke(ctx context.Context, req AccessRevokeRequest) (bool, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return false, err } diff --git a/pkg/cloudbroker/rg/affinity_group_computes.go b/pkg/cloudbroker/rg/affinity_group_computes.go index 809039d..18c3a0b 100644 --- a/pkg/cloudbroker/rg/affinity_group_computes.go +++ b/pkg/cloudbroker/rg/affinity_group_computes.go @@ -7,16 +7,21 @@ import ( "net/http" ) +// Request struct for get list of all computes with their relationships type AffinityGroupComputesRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Affinity group label + // Required: true AffinityGroup string `url:"affinityGroup"` } -func (rgrq AffinityGroupComputesRequest) Validate() error { +func (rgrq AffinityGroupComputesRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } - if rgrq.AffinityGroup == "" { return errors.New("validation-error: field AffinityGroup must be set") } @@ -24,23 +29,25 @@ func (rgrq AffinityGroupComputesRequest) Validate() error { return nil } -func (r RG) AffinityGroupComputes(ctx context.Context, req AffinityGroupComputesRequest) (AffinityGroupComputeList, error) { - if err := req.Validate(); err != nil { +// AffinityGroupComputes gets list of all computes with their relationships to another computes +func (r RG) AffinityGroupComputes(ctx context.Context, req AffinityGroupComputesRequest) (ListAffinityGroupCompute, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudbroker/rg/affinityGroupComputes" - agcListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - agcList := AffinityGroupComputeList{} + list := ListAffinityGroupCompute{} - if err := json.Unmarshal(agcListRaw, &agcList); err != nil { + if err := json.Unmarshal(res, &list); err != nil { return nil, err } - return agcList, nil + return list, nil } diff --git a/pkg/cloudbroker/rg/affinity_groups_get.go b/pkg/cloudbroker/rg/affinity_groups_get.go index 7a3ff30..8f4e3dd 100644 --- a/pkg/cloudbroker/rg/affinity_groups_get.go +++ b/pkg/cloudbroker/rg/affinity_groups_get.go @@ -7,16 +7,21 @@ import ( "net/http" ) +// Request struct for get list computes from affinity group type AffinityGroupsGetRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Label affinity group + // Required: true AffinityGroup string `url:"affinityGroup"` } -func (rgrq AffinityGroupsGetRequest) Validate() error { +func (rgrq AffinityGroupsGetRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } - if rgrq.AffinityGroup == "" { return errors.New("validation-error: field AffinityGroup must be set") } @@ -24,24 +29,26 @@ func (rgrq AffinityGroupsGetRequest) Validate() error { return nil } +// AffinityGroupsGet gets list computes in the specified affinity group func (r RG) AffinityGroupsGet(ctx context.Context, req AffinityGroupsGetRequest) ([]uint64, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return nil, err } url := "/cloudbroker/rg/affinityGroupsGet" - agListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - agList := make([]uint64, 0) + list := make([]uint64, 0) - err = json.Unmarshal(agListRaw, &agList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return agList, nil + return list, nil } diff --git a/pkg/cloudbroker/rg/affinity_groups_list.go b/pkg/cloudbroker/rg/affinity_groups_list.go index 27cdd6b..be1b010 100644 --- a/pkg/cloudbroker/rg/affinity_groups_list.go +++ b/pkg/cloudbroker/rg/affinity_groups_list.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list of affinity groups from resource group type AffinityGroupsListRequest struct { + // Resource group ID + // Required: true RGID uint64 `url:"rgId"` } -func (rgrq AffinityGroupsListRequest) Validate() error { +func (rgrq AffinityGroupsListRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -19,24 +22,26 @@ func (rgrq AffinityGroupsListRequest) Validate() error { return nil } +// AffinityGroupsList gets all currently defined affinity groups in this resource group with compute IDs func (r RG) AffinityGroupsList(ctx context.Context, req AffinityGroupsListRequest) (map[string][]uint64, error) { - if err := req.Validate(); err != nil { + err := req.validate() + if err != nil { return nil, err } url := "/cloudbroker/rg/affinityGroupsList" - agListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - agList := make(map[string][]uint64) + list := make(map[string][]uint64) - err = json.Unmarshal(agListRaw, &agList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return agList, nil + return list, nil } diff --git a/pkg/cloudbroker/rg/audits.go b/pkg/cloudbroker/rg/audits.go index c57034f..78138c3 100644 --- a/pkg/cloudbroker/rg/audits.go +++ b/pkg/cloudbroker/rg/audits.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get audit type AuditsRequest struct { + // Resource group ID + // Required: true RGID uint64 `url:"rgId"` } -func (rgrq AuditsRequest) Validate() error { +func (rgrq AuditsRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -19,23 +22,26 @@ func (rgrq AuditsRequest) Validate() error { return nil } -func (r RG) Audits(ctx context.Context, req AuditsRequest) (AuditList, error) { - if err := req.Validate(); err != nil { +// Audits gets audit records for the specified resource group object +func (r RG) Audits(ctx context.Context, req AuditsRequest) (ListAudits, error) { + err := req.validate() + if err != nil { return nil, err } url := "/cloudbroker/rg/audits" - auditListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - auditList := AuditList{} + list := ListAudits{} - if err := json.Unmarshal(auditListRaw, &auditList); err != nil { + err = json.Unmarshal(res, &list) + if err != nil { return nil, err } - return auditList, nil + return list, nil } diff --git a/pkg/cloudbroker/rg/create.go b/pkg/cloudbroker/rg/create.go index f30a47d..c80fb64 100644 --- a/pkg/cloudbroker/rg/create.go +++ b/pkg/cloudbroker/rg/create.go @@ -5,45 +5,123 @@ import ( "errors" "net/http" "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for create resource group type CreateRequest struct { - AccountID uint64 `url:"accountId"` - GID uint64 `url:"gid"` - Name string `url:"name"` - MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` - MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` - MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + // Account, which will own this resource group + // Required: true + AccountID uint64 `url:"accountId"` + + // Grid ID + // Required: true + GID uint64 `url:"gid"` + + // Name of this resource group. Must be unique within the account + // Required: true + Name string `url:"name"` + + // Max size of memory in MB + // Required: false + MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` + + // Max size of aggregated virtual disks in GB + // Required: false + MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` + + // Max number of CPU cores + // Required: false + MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + + // Max sent/received network transfer peering + // Required: false MaxNetworkPeerTransfer uint64 `url:"maxNetworkPeerTransfer,omitempty"` - MaxNumPublicIP uint64 `url:"maxNetworkPeerTransfer,omitempty"` - Owner string `url:"owner,omitempty"` - DefNet string `url:"def_net,omitempty"` - IPCIDR string `url:"ipcidr,omitempty"` - Desc string `url:"desc,omitempty"` - Reason string `url:"reason,omitempty"` - ExtNetID uint64 `url:"extNetId,omitempty"` - ExtIP string `url:"extIp,omitempty"` - RegisterComputes bool `url:"registerComputes,omitempty"` + + // Max number of assigned public IPs + // Required: false + MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"` + + // Username - owner of this resource group. + // Leave blank to set current user as owner + // Required: false + Owner string `url:"owner,omitempty"` + + // Type of the default network for this resource group. + // virtual machines created in this resource group will be by default connected to this network. + // Should be one of: + // - PRIVATE + // - PUBLIC + // - NONE + // Required: false + DefNet string `url:"def_net,omitempty"` + + // Private network IP CIDR if default network PRIVATE + // Required: false + IPCIDR string `url:"ipcidr,omitempty"` + + // Text description of this resource group + // Required: false + Description string `url:"desc,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` + + // External network ID + // Required: false + ExtNetID uint64 `url:"extNetId,omitempty"` + + // External IP address + // Required: false + ExtIP string `url:"extIp,omitempty"` + + // Register computes in registration system + // Required: false + RegisterComputes bool `url:"registerComputes,omitempty"` + + // List of strings with pools i.e.: ["sep1_poolName1", "sep2_poolName2"] + // Required: false + UniqPools []string `url:"unuqPools,omitempty"` + + // Resource types available to create in this account + // Each element in a resource type slice should be one of: + // - compute + // - vins + // - k8s + // - openshift + // - lb + // - flipgroup + // Required: false + ResTypes []string `url:"resourceTypes,omitempty"` } -func (rgrq CreateRequest) Validate() error { +func (rgrq CreateRequest) validate() error { if rgrq.AccountID == 0 { return errors.New("field AccountID can not be empty or equal to 0") } - if rgrq.GID == 0 { return errors.New("field GID can not be empty or equal to 0") } - if len(rgrq.Name) < 2 { return errors.New("field Name can not be shorter than two bytes") } + if len(rgrq.ResTypes) > 0 { + for _, value := range rgrq.ResTypes { + validate := validators.StringInSlice(value, []string{"compute", "vins", "k8s", "openshift", "lb", "flipgroup"}) + if !validate { + return errors.New("validation-error: Every resource type specified should be one of [compute, vins, k8s, openshift, lb, flipgroup]") + } + } + } return nil } +// Create creates resource group func (r RG) Create(ctx context.Context, req CreateRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } diff --git a/pkg/cloudbroker/rg/delete.go b/pkg/cloudbroker/rg/delete.go index f38b844..06178b4 100644 --- a/pkg/cloudbroker/rg/delete.go +++ b/pkg/cloudbroker/rg/delete.go @@ -7,14 +7,27 @@ import ( "strconv" ) +// Request struct for delete resource group type DeleteRequest struct { - RGID uint64 `url:"rgId"` - Force bool `url:"force,omitempty"` - Permanently bool `url:"permanently,omitempty"` - Reason string `url:"reason,omitempty"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Set to True if you want force delete non-empty resource group + // Required: false + Force bool `url:"force,omitempty"` + + // Set to True if you want to destroy resource group and all linked resources, if any, immediately. + // Otherwise, they will be placed into recycle bin and could be restored later within recycle bin's purge period + // Required: false + Permanently bool `url:"permanently,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` } -func (rgrq DeleteRequest) Validate() error { +func (rgrq DeleteRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -22,8 +35,9 @@ func (rgrq DeleteRequest) Validate() error { return nil } +// Delete deletes resource group func (r RG) Delete(ctx context.Context, req DeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -41,4 +55,4 @@ func (r RG) Delete(ctx context.Context, req DeleteRequest) (bool, error) { } return result, nil -} \ No newline at end of file +} diff --git a/pkg/cloudbroker/rg/disable.go b/pkg/cloudbroker/rg/disable.go index a373690..6b187a9 100644 --- a/pkg/cloudbroker/rg/disable.go +++ b/pkg/cloudbroker/rg/disable.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for disable resource group type DisableRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq DisableRequest) Validate() error { +func (rgrq DisableRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -20,8 +26,9 @@ func (rgrq DisableRequest) Validate() error { return nil } +// Disable disables resource group by ID func (r RG) Disable(ctx context.Context, req DisableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -39,4 +46,4 @@ func (r RG) Disable(ctx context.Context, req DisableRequest) (bool, error) { } return result, nil -} \ No newline at end of file +} diff --git a/pkg/cloudbroker/rg/enable.go b/pkg/cloudbroker/rg/enable.go index bc1b49d..bd23aed 100644 --- a/pkg/cloudbroker/rg/enable.go +++ b/pkg/cloudbroker/rg/enable.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for enable resource group type EnableRequest struct { - RGID uint64 `url:"rgId"` - Reason string `url:"reason"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` } -func (rgrq EnableRequest) Validate() error { +func (rgrq EnableRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -20,8 +26,9 @@ func (rgrq EnableRequest) Validate() error { return nil } +// Enable enables resource group by ID func (r RG) Enable(ctx context.Context, req EnableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -39,4 +46,4 @@ func (r RG) Enable(ctx context.Context, req EnableRequest) (bool, error) { } return result, nil -} \ No newline at end of file +} diff --git a/pkg/cloudbroker/rg/get.go b/pkg/cloudbroker/rg/get.go index 145d9b7..32e4a4d 100644 --- a/pkg/cloudbroker/rg/get.go +++ b/pkg/cloudbroker/rg/get.go @@ -7,12 +7,18 @@ import ( "net/http" ) +// Request struct for get detailed information about resource group type GetRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq GetRequest) Validate() error { +func (rgrq GetRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -20,8 +26,9 @@ func (rgrq GetRequest) Validate() error { return nil } -func (r RG) Get(ctx context.Context, req GetRequest) (*ResourceGroup, error) { - err := req.Validate() +// Get gets current configuration of the resource group +func (r RG) Get(ctx context.Context, req GetRequest) (*RecordRG, error) { + err := req.validate() if err != nil { return nil, err } @@ -33,12 +40,12 @@ func (r RG) Get(ctx context.Context, req GetRequest) (*ResourceGroup, error) { return nil, err } - getResult := ResourceGroup{} + info := RecordRG{} - err = json.Unmarshal(res, &getResult) + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return &getResult, nil + return &info, nil } diff --git a/pkg/cloudbroker/rg/list.go b/pkg/cloudbroker/rg/list.go index 140a015..3f22c35 100644 --- a/pkg/cloudbroker/rg/list.go +++ b/pkg/cloudbroker/rg/list.go @@ -6,13 +6,23 @@ import ( "net/http" ) +// Request struct for get list of resource groups type ListRequest struct { - IncludeDeleted bool `url:"includedeleted,omitempty"` - Page uint64 `url:"page,omitempty"` - Size uint64 `url:"size,omitempty"` + // Included deleted resource groups + // Required: false + IncludeDeleted bool `url:"includedeleted,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` } -func (r RG) List(ctx context.Context, req ListRequest) (List, error) { +// List gets list of all resource groups the user has access to +func (r RG) List(ctx context.Context, req ListRequest) (ListRG, error) { url := "/cloudbroker/rg/list" res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) @@ -20,7 +30,7 @@ func (r RG) List(ctx context.Context, req ListRequest) (List, error) { return nil, err } - list := List{} + list := ListRG{} err = json.Unmarshal(res, &list) if err != nil { diff --git a/pkg/cloudbroker/rg/list_computes.go b/pkg/cloudbroker/rg/list_computes.go index 8623b85..93f3011 100644 --- a/pkg/cloudbroker/rg/list_computes.go +++ b/pkg/cloudbroker/rg/list_computes.go @@ -7,12 +7,18 @@ import ( "net/http" ) +// Request struct for get list of computes type ListComputesRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq ListComputesRequest) Validate() error { +func (rgrq ListComputesRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -20,8 +26,9 @@ func (rgrq ListComputesRequest) Validate() error { return nil } +// ListComputes gets list of all compute instances under specified resource group, accessible by the user func (r RG) ListComputes(ctx context.Context, req ListComputesRequest) (ListComputes, error) { - err := req.Validate() + err := req.validate() if err != nil { return nil, err } @@ -33,12 +40,12 @@ func (r RG) ListComputes(ctx context.Context, req ListComputesRequest) (ListComp return nil, err } - listComputes := ListComputes{} + list := ListComputes{} - err = json.Unmarshal(res, &listComputes) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return listComputes, nil + return list, nil } diff --git a/pkg/cloudbroker/rg/list_deleted.go b/pkg/cloudbroker/rg/list_deleted.go index 57965a6..d075518 100644 --- a/pkg/cloudbroker/rg/list_deleted.go +++ b/pkg/cloudbroker/rg/list_deleted.go @@ -6,12 +6,19 @@ import ( "net/http" ) +// Request struct for get list deleted resource groups type ListDeletedRequest struct { + // Page number + // Required: false Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false Size uint64 `url:"size,omitempty"` } -func (r RG) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListDeleted, error) { +// ListDeleted gets list all deleted resource groups the user has access to +func (r RG) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListRG, error) { url := "/cloudbroker/rg/listDeleted" res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) @@ -19,12 +26,12 @@ func (r RG) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListDelete return nil, err } - listDeleted := ListDeleted{} + list := ListRG{} - err = json.Unmarshal(res, &listDeleted) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return listDeleted, nil + return list, nil } diff --git a/pkg/cloudbroker/rg/list_lb.go b/pkg/cloudbroker/rg/list_lb.go index 9945d6b..7a7e48f 100644 --- a/pkg/cloudbroker/rg/list_lb.go +++ b/pkg/cloudbroker/rg/list_lb.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list load balancers type ListLBRequest struct { + // Resource group ID + // Required: true RGID uint64 `url:"rgId"` } -func (rgrq ListLBRequest) Validate() error { +func (rgrq ListLBRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -19,25 +22,26 @@ func (rgrq ListLBRequest) Validate() error { return nil } +// ListLB gets list all load balancers in the specified resource group, accessible by the user func (r RG) ListLB(ctx context.Context, req ListLBRequest) (ListLB, error) { - err := req.Validate() + err := req.validate() if err != nil { return nil, err } url := "/cloudbroker/rg/listLb" - lbListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - lbList := ListLB{} + list := ListLB{} - err = json.Unmarshal(lbListRaw, &lbList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return lbList, nil + return list, nil } diff --git a/pkg/cloudbroker/rg/list_pfw.go b/pkg/cloudbroker/rg/list_pfw.go index 205f017..f657286 100644 --- a/pkg/cloudbroker/rg/list_pfw.go +++ b/pkg/cloudbroker/rg/list_pfw.go @@ -7,11 +7,14 @@ import ( "net/http" ) +// Request struct for get list port forward rules type ListPFWRequest struct { + // Resource group ID + // Required: true RGID uint64 `url:"rgId"` } -func (rgrq ListPFWRequest) Validate() error { +func (rgrq ListPFWRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -19,25 +22,26 @@ func (rgrq ListPFWRequest) Validate() error { return nil } +// ListPFW gets list port forward rules for the specified resource group func (r RG) ListPFW(ctx context.Context, req ListPFWRequest) (ListPFW, error) { - err := req.Validate() + err := req.validate() if err != nil { return nil, err } url := "/cloudbroker/rg/listPFW" - pfwListRaw, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) if err != nil { return nil, err } - pfwList := ListPFW{} + list := ListPFW{} - err = json.Unmarshal(pfwListRaw, &pfwList) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return pfwList, nil + return list, nil } diff --git a/pkg/cloudbroker/rg/list_vins.go b/pkg/cloudbroker/rg/list_vins.go index 0a0a132..946b6e1 100644 --- a/pkg/cloudbroker/rg/list_vins.go +++ b/pkg/cloudbroker/rg/list_vins.go @@ -7,12 +7,18 @@ import ( "net/http" ) +// Request struct for get list VINSes type ListVINSRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq ListVINSRequest) Validate() error { +func (rgrq ListVINSRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -20,8 +26,9 @@ func (rgrq ListVINSRequest) Validate() error { return nil } +// ListVINS gets list all ViNSes under specified resource group, accessible by the user func (r RG) ListVINS(ctx context.Context, req ListVINSRequest) (ListVINS, error) { - err := req.Validate() + err := req.validate() if err != nil { return nil, err } @@ -33,12 +40,12 @@ func (r RG) ListVINS(ctx context.Context, req ListVINSRequest) (ListVINS, error) return nil, err } - listVINS := ListVINS{} + list := ListVINS{} - err = json.Unmarshal(res, &listVINS) + err = json.Unmarshal(res, &list) if err != nil { return nil, err } - return listVINS, nil + return list, nil } diff --git a/pkg/cloudbroker/rg/mass_delete.go b/pkg/cloudbroker/rg/mass_delete.go index 3ad1cad..cea1d42 100644 --- a/pkg/cloudbroker/rg/mass_delete.go +++ b/pkg/cloudbroker/rg/mass_delete.go @@ -6,14 +6,29 @@ import ( "net/http" ) +// Request struct for delete several resource groups type MassDeleteRequest struct { - RGIDs []uint64 `url:"rgIds"` - Force bool `url:"force,omitempty"` - Permanently bool `url:"permanently,omitempty"` - Reason string `url:"reason,omitempty"` + // IDs of the resource groups + // Required: true + RGIDs []uint64 `url:"rgIds"` + + // Set to true if you want force delete non-empty resource groups + // Required: false + Force bool `url:"force,omitempty"` + + // Set to true if you want to destroy resource group and all linked + // resources, if any, immediately. + // Otherwise, they will be placed into recycle bin and could be + // restored later within recycle bins purge period + // Required: false + Permanently bool `url:"permanently,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` } -func (rgrq MassDeleteRequest) Validate() error { +func (rgrq MassDeleteRequest) validate() error { if len(rgrq.RGIDs) == 0 { return errors.New("validation-error: field RGIDs must be set") } @@ -21,8 +36,9 @@ func (rgrq MassDeleteRequest) Validate() error { return nil } +// MassDelete starts jobs to delete several resource groups func (r RG) MassDelete(ctx context.Context, req MassDeleteRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/rg/mass_disable.go b/pkg/cloudbroker/rg/mass_disable.go index d62b3c1..cde6817 100644 --- a/pkg/cloudbroker/rg/mass_disable.go +++ b/pkg/cloudbroker/rg/mass_disable.go @@ -6,12 +6,18 @@ import ( "net/http" ) +// Request struct for disable several resource groups type MassDisableRequest struct { - RGIDs []uint64 `url:"rgIds"` - Reason string `url:"reason,omitempty"` + // IDs of the resource groups + // Required: true + RGIDs []uint64 `url:"rgIds"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` } -func (rgrq MassDisableRequest) Validate() error { +func (rgrq MassDisableRequest) validate() error { if len(rgrq.RGIDs) == 0 { return errors.New("validation-error: field RGIDs must be set") } @@ -19,8 +25,9 @@ func (rgrq MassDisableRequest) Validate() error { return nil } +// MassDisable start jobs to disable several resource groups func (r RG) MassDisable(ctx context.Context, req MassDisableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/rg/mass_enable.go b/pkg/cloudbroker/rg/mass_enable.go index 884adde..80a1971 100644 --- a/pkg/cloudbroker/rg/mass_enable.go +++ b/pkg/cloudbroker/rg/mass_enable.go @@ -6,12 +6,18 @@ import ( "net/http" ) +// Request struct for enable several resource groups type MassEnableRequest struct { - RGIDs []uint64 `url:"rgIds"` - Reason string `url:"reason,omitempty"` + // IDs of the resource groups + // Required: true + RGIDs []uint64 `url:"rgIds"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` } -func (rgrq MassEnableRequest) Validate() error { +func (rgrq MassEnableRequest) validate() error { if len(rgrq.RGIDs) == 0 { return errors.New("validation-error: field RGIDs must be set") } @@ -19,8 +25,9 @@ func (rgrq MassEnableRequest) Validate() error { return nil } +// MassEnable start jobs to enable several resource groups func (r RG) MassEnable(ctx context.Context, req MassEnableRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/rg/models.go b/pkg/cloudbroker/rg/models.go index 55903b3..35be0b3 100644 --- a/pkg/cloudbroker/rg/models.go +++ b/pkg/cloudbroker/rg/models.go @@ -1,264 +1,622 @@ package rg -type Audit struct { - Call string `json:"call"` +// Main information about audit +type ItemAudit struct { + // Call + Call string `json:"call"` + + // Response time ResponseTime float64 `json:"responsetime"` - StatusCode uint64 `json:"statuscode"` - Timestamp float64 `json:"timestamp"` - User string `json:"user"` -} -type AuditList []Audit -type Current struct { - CPU uint64 `json:"cpu"` - DiskSize uint64 `json:"disksize"` - ExtIPs uint64 `json:"extips"` - ExtTraffic uint64 `json:"exttraffic"` - GPU uint64 `json:"gpu"` - RAM uint64 `json:"ram"` + // Status code + StatusCode uint64 `json:"statuscode"` + + // Timestamp + Timestamp float64 `json:"timestamp"` + + // User + User string `json:"user"` } -type Reserved struct { - CPU uint64 `json:"cpu"` - DiskSize uint64 `json:"disksize"` - ExtIPs uint64 `json:"extips"` +// List Audits +type ListAudits []ItemAudit + +// Reservation information of usage +type Reservation struct { + // Number of CPU + CPU uint64 `json:"cpu"` + + // Disk size + DiskSize uint64 `json:"disksize"` + + // External IPs + ExtIPs uint64 `json:"extips"` + + // External traffic ExtTraffic uint64 `json:"exttraffic"` - GPU uint64 `json:"gpu"` - RAM uint64 `json:"ram"` + + // Number of GPU + GPU uint64 `json:"gpu"` + + // Number of RAM + RAM uint64 `json:"ram"` } +// Resources usage information type Resources struct { - Current Current `json:"Current"` - Reserved Reserved `json:"Reserved"` + // Current information + Current Reservation `json:"Current"` + + // Reserved information + Reserved Reservation `json:"Reserved"` } +// Access Control List type ACL struct { - Explicit bool `json:"explicit"` - GUID string `json:"guid"` - Right string `json:"right"` - Status string `json:"status"` - Type string `json:"type"` + // Explicit + Explicit bool `json:"explicit"` + + // GUID + GUID string `json:"guid"` + + // Right + Right string `json:"right"` + + // Status + Status string `json:"status"` + + // Type + Type string `json:"type"` + + // User group ID UserGroupID string `json:"userGroupId"` } +// List ACL +type ListACL []ACL + +// Resource limits type ResourceLimits struct { - CuC float64 `json:"CU_C"` - CuD float64 `json:"CU_D"` - CuI float64 `json:"CU_I"` - CuM float64 `json:"CU_M"` - CuNp float64 `json:"CU_NP"` + // CUC + CUC float64 `json:"CU_C"` + + // CUD + CuD float64 `json:"CU_D"` + + // CUI + CUI float64 `json:"CU_I"` + + // CUM + CUM float64 `json:"CU_M"` + + // CUNP + CUNP float64 `json:"CU_NP"` + + // GPU units GPUUnits float64 `json:"gpu_units"` } -type ResourceGroup struct { +// Detailed information about resource group +type RecordRG struct { + // Resource information Resources Resources `json:"Resources"` - InfoResponse + + // Main information about resource group + ItemRG } -type InfoResponse struct { - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - ACL []ACL `json:"acl"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DefNetID int64 `json:"def_net_id"` - DefNetType string `json:"def_net_type"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - Desc string `json:"desc"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - LockStatus string `json:"lockStatus"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - RegisterComputes bool `json:"registerComputes"` - ResourceLimits ResourceLimits `json:"resourceLimits"` - Secret string `json:"secret"` - Status string `json:"status"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - VINS []interface{} `json:"vins"` - VMs []interface{} `json:"vms"` +// Main information about resource group +type ItemRG struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // List ACL + ACL ListACL `json:"acl"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // DefNet ID + DefNetID int64 `json:"def_net_id"` + + // DefNet type + DefNetType string `json:"def_net_type"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Lock status + LockStatus string `json:"lockStatus"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Register computes + RegisterComputes bool `json:"registerComputes"` + + // Resource limits + ResourceLimits ResourceLimits `json:"resourceLimits"` + + // Secret + Secret string `json:"secret"` + + // Status + Status string `json:"status"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // List VINS IDs + VINS []uint64 `json:"vins"` + + // List virtual machine IDs + VMs []uint64 `json:"vms"` + + // Resource types list + ResTypes []string `json:"resTypes"` + + // Uniq pools + UniqPools []string `json:"uniqPools"` } -type List []InfoResponse +// List resource groups +type ListRG []ItemRG + +// Main information about affinity group +type ItemAffinityGroupCompute struct { + // Compute ID + ComputeID uint64 `json:"computeId"` + + // Other node + OtherNode []uint64 `json:"otherNode"` -type ListDeleted []InfoResponse + // Other node indirect + OtherNodeIndirect []uint64 `json:"otherNodeIndirect"` -type AffinityGroupCompute struct { - ComputeID uint64 `json:"computeId"` - OtherNode []uint64 `json:"otherNode"` - OtherNodeIndirect []uint64 `json:"otherNodeIndirect"` + // Other node indirect soft OtherNodeIndirectSoft []uint64 `json:"otherNodeIndirectSoft"` - OtherNodeSoft []uint64 `json:"otherNodeSoft"` - SameNode []uint64 `json:"sameNode"` - SameNodeSoft []uint64 `json:"sameNodeSoft"` + + // Other node soft + OtherNodeSoft []uint64 `json:"otherNodeSoft"` + + // Same node + SameNode []uint64 `json:"sameNode"` + + // Same node soft + SameNodeSoft []uint64 `json:"sameNodeSoft"` } -type AffinityGroupComputeList []AffinityGroupCompute +// List of affinity groups +type ListAffinityGroupCompute []ItemAffinityGroupCompute + +// Main information about affinity rule +type ItemAffinityRule struct { + // GUID + GUID string `json:"guid"` + + // Key + Key string `json:"key"` + + // Mode + Mode string `json:"mode"` -type AffinityRules struct { - GUID string `json:"guid"` - Key string `json:"key"` - Mode string `json:"mode"` - Policy string `json:"policy"` + // Policy + Policy string `json:"policy"` + + // Topology Topology string `json:"topology"` - Value string `json:"value"` + + // Value + Value string `json:"value"` } -type Compute struct { - AccountID uint64 `json:"accountId"` - AccountName string `json:"accountName"` - AffinityLabel string `json:"affinityLabel"` - AffinityRules []AffinityRules `json:"affinityRules"` - AffinityWeight uint64 `json:"affinityWeight"` - AntiAffinityRules []interface{} `json:"antiAffinityRules"` - CPUs uint64 `json:"cpus"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - ID uint64 `json:"id"` - Name string `json:"name"` - RAM uint64 `json:"ram"` - Registered bool `json:"registered"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - TotalDisksSize uint64 `json:"totalDisksSize"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - UserManaged bool `json:"userManaged"` - VINSConnected uint64 `json:"vinsConnected"` +// List affinity rules +type ListAffinityRules []ItemAffinityRule + +// Main information about compute +type ItemCompute struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Affinity label + AffinityLabel string `json:"affinityLabel"` + + // List affinity rules + AffinityRules ListAffinityRules `json:"affinityRules"` + + // Affinity weight + AffinityWeight uint64 `json:"affinityWeight"` + + // Anti affinity rules + AntiAffinityRules []interface{} `json:"antiAffinityRules"` + + // Number of CPU + CPUs uint64 `json:"cpus"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Number of RAM + RAM uint64 `json:"ram"` + + // Registered + Registered bool `json:"registered"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Total disks size + TotalDisksSize uint64 `json:"totalDisksSize"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // User managed + UserManaged bool `json:"userManaged"` + + // VINS connected + VINSConnected uint64 `json:"vinsConnected"` } -type ListComputes []Compute +// List computes +type ListComputes []ItemCompute -type VINS struct { - AccountID uint64 `json:"accountId"` +// Main information about VINS +type ItemVINS struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name AccountName string `json:"accountName"` - Computes uint64 `json:"computes"` - CreatedBy string `json:"createdBy"` + + // Computes + Computes uint64 `json:"computes"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time DeletedTime uint64 `json:"deletedTime"` - ExternalIP string `json:"externalIP"` - ID uint64 `json:"id"` - Name string `json:"name"` - Network string `json:"network"` + + // External IP + ExternalIP string `json:"externalIP"` + + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Network + Network string `json:"network"` + + // PriVNFDev ID PriVNFDevID uint64 `json:"priVnfDevId"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - Status string `json:"status"` - UpdatedBy string `json:"updatedBy"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Status + Status string `json:"status"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time UpdatedTime uint64 `json:"updatedTime"` } -type ListVINS []VINS +// List VINSes +type ListVINS []ItemVINS + +// Main information about port forward +type ItemPFW struct { + // Public port end + PublicPortEnd uint64 `json:"Public Port End"` -type PFW struct { - PublicPortEnd uint64 `json:"Public Port End"` + // Public port start PublicPortStart uint64 `json:"Public Port Start"` - VMID uint64 `json:"VM ID"` - VMIP string `json:"VM IP"` - VMName string `json:"VM Name"` - VMPort uint64 `json:"VM Port"` - VINSID uint64 `json:"ViNS ID"` - VINSName string `json:"ViNS Name"` + + // Virtual machine ID + VMID uint64 `json:"VM ID"` + + // Virtual machine IP + VMIP string `json:"VM IP"` + + // Virtual machine name + VMName string `json:"VM Name"` + + // Virtual machine port + VMPort uint64 `json:"VM Port"` + + // VINS ID + VINSID uint64 `json:"ViNS ID"` + + // VINS name + VINSName string `json:"ViNS Name"` } -type ListPFW []PFW +// List PFWs +type ListPFW []ItemPFW +// Server settings type ServerSettings struct { + // Inter + Inter uint64 `json:"inter"` + + // GUID + GUID string `json:"guid"` + + // Down inter DownInter uint64 `json:"downinter"` - Fall uint64 `json:"fall"` - GUID string `json:"guid"` - Inter uint64 `json:"inter"` - MaxConn uint64 `json:"maxconn"` - MaxQueue uint64 `json:"maxqueue"` - Rise uint64 `json:"rise"` + + // Rise + Rise uint64 `json:"rise"` + + // Fall + Fall uint64 `json:"fall"` + + // Slow start SlowStart uint64 `json:"slowstart"` - Weight uint64 `json:"weight"` + + // Max connections + MaxConn uint64 `json:"maxconn"` + + // Max queue + MaxQueue uint64 `json:"maxqueue"` + + // Weight + Weight uint64 `json:"weight"` } -type Server struct { - Address string `json:"address"` - Check string `json:"check"` - GUID string `json:"guid"` - Name string `json:"name"` - Port uint64 `json:"port"` +// Main information about server +type ItemServer struct { + // Address + Address string `json:"address"` + + // Check + Check string `json:"check"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` + + // Port + Port uint64 `json:"port"` + + // Server settings ServerSettings ServerSettings `json:"serverSettings"` } -type Backends struct { - Algorithm string `json:"algorithm"` - GUID string `json:"guid"` - Name string `json:"name"` +// List of servers +type ListServers []ItemServer + +// Main information about backend +type ItemBackend struct { + // Algorithm + Algorithm string `json:"algorithm"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` + + // Server settings ServerDefaultSettings ServerSettings `json:"serverDefaultSettings"` - Servers []Server `json:"servers"` + + // List of servers + Servers ListServers `json:"servers"` } -type Binding struct { +// List of backends +type ListBackends []ItemBackend + +// Main information of binding +type ItemBinding struct { + // Address Address string `json:"address"` - GUID string `json:"guid"` - Name string `json:"name"` - Port uint64 `json:"port"` -} -type Frontend struct { - Backend string `json:"backend"` - Bindings []Binding `json:"bindings"` - GUID string `json:"guid"` - Name string `json:"name"` + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` + + // Port + Port uint64 `json:"port"` } -type PrimaryNode struct { - BackendIP string `json:"backendIp"` - ComputeID uint64 `json:"computeId"` - FrontendIP string `json:"frontendIp"` - GUID string `json:"guid"` - MgmtIP string `json:"mgmtIp"` - NetworkID uint64 `json:"networkId"` +// List of bindings +type ListBindings []ItemBinding + +// Main information about frontend +type ItemFrontend struct { + // Backend + Backend string `json:"backend"` + + // List of bindings + Bindings ListBindings `json:"bindings"` + + // GUID + GUID string `json:"guid"` + + // Name + Name string `json:"name"` } -type SecondaryNode struct { - BackendIP string `json:"backendIp"` - ComputeID uint64 `json:"computeId"` +// List of frontends +type ListFrontends []ItemFrontend + +// Main information about node +type RecordNode struct { + // Backend IP + BackendIP string `json:"backendIp"` + + // Compute ID + ComputeID uint64 `json:"computeId"` + + // Frontend IP FrontendIP string `json:"frontendIp"` - GUID string `json:"guid"` - MgmtIP string `json:"mgmtIp"` - NetworkID uint64 `json:"networkId"` + + // GUID + GUID string `json:"guid"` + + // MGMT IP + MGMTIP string `json:"mgmtIp"` + + // Network ID + NetworkID uint64 `json:"networkId"` } -type LB struct { - HAMode bool `json:"HAmode"` - ACL []ACL `json:"acl"` - Backends []Backends `json:"backends"` - CreatedBy string `json:"createdBy"` - CreatedTime uint64 `json:"createdTime"` - DeletedBy string `json:"deletedBy"` - DeletedTime uint64 `json:"deletedTime"` - Desc string `json:"desc"` - DpAPIUser string `json:"dpApiUser"` - ExtNetID uint64 `json:"extnetId"` - Frontends []Frontend `json:"frontends"` - GID uint64 `json:"gid"` - GUID uint64 `json:"guid"` - ID uint64 `json:"id"` - ImageID uint64 `json:"imageId"` - Milestones uint64 `json:"milestones"` - Name string `json:"name"` - PrimaryNode PrimaryNode `json:"primaryNode"` - RGID uint64 `json:"rgId"` - RGName string `json:"rgName"` - SecondaryNode SecondaryNode `json:"secondaryNode"` - Status string `json:"status"` - TechStatus string `json:"techStatus"` - UpdatedBy string `json:"updatedBy"` - UpdatedTime uint64 `json:"updatedTime"` - VINSID uint64 `json:"vinsId"` +// Main information about load balancer +type ItemLB struct { + // HAMode + HAMode bool `json:"HAmode"` + + // List ACL + ACL ListACL `json:"acl"` + + // List backends + Backends ListBackends `json:"backends"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // DPAPI user + DPAPIUser string `json:"dpApiUser"` + + // External network ID + ExtNetID uint64 `json:"extnetId"` + + // List of frontends + Frontends ListFrontends `json:"frontends"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Image ID + ImageID uint64 `json:"imageId"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Primary node + PrimaryNode RecordNode `json:"primaryNode"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // Secondary node + SecondaryNode RecordNode `json:"secondaryNode"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // VINS ID + VINSID uint64 `json:"vinsId"` } -type ListLB []LB +// List load balancers +type ListLB []ItemLB diff --git a/pkg/cloudbroker/rg/restore.go b/pkg/cloudbroker/rg/restore.go index 8f7a079..4e0773e 100644 --- a/pkg/cloudbroker/rg/restore.go +++ b/pkg/cloudbroker/rg/restore.go @@ -7,12 +7,18 @@ import ( "strconv" ) +// Request struct for restore resource group type RestoreRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq RestoreRequest) Validate() error { +func (rgrq RestoreRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -20,8 +26,9 @@ func (rgrq RestoreRequest) Validate() error { return nil } +// Restore restores resource group from recycle bin func (r RG) Restore(ctx context.Context, req RestoreRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } @@ -39,4 +46,4 @@ func (r RG) Restore(ctx context.Context, req RestoreRequest) (bool, error) { } return result, nil -} \ No newline at end of file +} diff --git a/pkg/cloudbroker/rg/rg.go b/pkg/cloudbroker/rg/rg.go index 73f48ca..c842504 100644 --- a/pkg/cloudbroker/rg/rg.go +++ b/pkg/cloudbroker/rg/rg.go @@ -1,11 +1,16 @@ +// API Actors for managing resource groups. These actors are the final API for end users to manage resource groups package rg -import "github.com/rudecs/decort-sdk/interfaces" +import ( + "github.com/rudecs/decort-sdk/interfaces" +) +// Structure for creating request to resource group type RG struct { client interfaces.Caller } +// Builder for resource group endpoints func New(client interfaces.Caller) *RG { return &RG{ client: client, diff --git a/pkg/cloudbroker/rg/set_def_net.go b/pkg/cloudbroker/rg/set_def_net.go index 0945283..29e1b59 100644 --- a/pkg/cloudbroker/rg/set_def_net.go +++ b/pkg/cloudbroker/rg/set_def_net.go @@ -3,23 +3,38 @@ package rg import ( "context" "errors" - "github.com/rudecs/decort-sdk/internal/validators" "net/http" "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for set default network type SetDefNetRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Network type + // Should be one of: + // - "PUBLIC" + // - "PRIVATE" + // Required: true NetType string `url:"netType"` - NetID uint64 `url:"netId,omitempty"` - Reason string `url:"reason,omitempty"` + + // Network ID + // Required: false + NetID uint64 `url:"netId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` } -func (rgrq SetDefNetRequest) Validate() error { +func (rgrq SetDefNetRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } - validate := validators.StringInSlice(rgrq.NetType, []string{"PUBLIC", "PRIVATE"}) if !validate { return errors.New("validation-error: field NetType must be one of PRIVATE or PUBLIC") @@ -28,8 +43,9 @@ func (rgrq SetDefNetRequest) Validate() error { return nil } +// SetDefNet sets default network for attach associated virtual machines func (r RG) SetDefNet(ctx context.Context, req SetDefNetRequest) (uint64, error) { - err := req.Validate() + err := req.validate() if err != nil { return 0, err } diff --git a/pkg/cloudbroker/rg/update.go b/pkg/cloudbroker/rg/update.go index 1239b90..959aa93 100644 --- a/pkg/cloudbroker/rg/update.go +++ b/pkg/cloudbroker/rg/update.go @@ -5,31 +5,86 @@ import ( "errors" "net/http" "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" ) +// Request struct for update resource group type UpdateRequest struct { - RGID uint64 `url:"rgId"` - Name string `url:"name,omitempty"` - Desc string `url:"desc,omitempty"` - MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` - MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` - MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // New name + // Required: false + Name string `url:"name,omitempty"` + + // New description + // Required: false + Description string `url:"desc,omitempty"` + + // Max size of memory in MB + // Required: false + MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` + + // Max size of aggregated virtual disks in GB + // Required: false + MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` + + // Max number of CPU cores + // Required: false + MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` + + // Max sent/received network transfer peering + // Required: false MaxNetworkPeerTransfer uint64 `url:"maxNetworkPeerTransfer,omitempty"` - MaxNumPublicIP uint64 `url:"maxNetworkPeerTransfer,omitempty"` - RegisterComputes bool `url:"registerComputes,omitempty"` - Reason string `url:"reason"` + + // Max number of assigned public IPs + // Required: false + MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"` + + // Register computes in registration system + // Required: false + RegisterComputes bool `url:"registerComputes,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` + + // List of strings with pools i.e.: ["sep1_poolName1", "sep2_poolName2", etc] + // Required: false + UniqPools []string `url:"uniqPools,omitempty"` + + // Resource types available to create in this account + // Each element in a resource type slice should be one of: + // - compute + // - vins + // - k8s + // - openshift + // - lb + // - flipgroup + // Required: false + ResTypes []string `url:"resourceTypes,omitempty"` } -func (rgrq UpdateRequest) Validate() error { +func (rgrq UpdateRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } - + if len(rgrq.ResTypes) > 0 { + for _, value := range rgrq.ResTypes { + validate := validators.StringInSlice(value, []string{"compute", "vins", "k8s", "openshift", "lb", "flipgroup"}) + if !validate { + return errors.New("validation-error: Every resource type specified should be one of [compute, vins, k8s, openshift, lb, flipgroup]") + } + } + } return nil } +// Update updates resource group func (r RG) Update(ctx context.Context, req UpdateRequest) (bool, error) { - err := req.Validate() + err := req.validate() if err != nil { return false, err } diff --git a/pkg/cloudbroker/rg/usage.go b/pkg/cloudbroker/rg/usage.go index 8a13f79..e182d6e 100644 --- a/pkg/cloudbroker/rg/usage.go +++ b/pkg/cloudbroker/rg/usage.go @@ -7,12 +7,18 @@ import ( "net/http" ) +// Request struct for get report of resource usage type UsageRequest struct { - RGID uint64 `url:"rgId"` + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Reason for action + // Required: false Reason string `url:"reason,omitempty"` } -func (rgrq UsageRequest) Validate() error { +func (rgrq UsageRequest) validate() error { if rgrq.RGID == 0 { return errors.New("validation-error: field RGID must be set") } @@ -20,8 +26,9 @@ func (rgrq UsageRequest) Validate() error { return nil } -func (r RG) Usage(ctx context.Context, req UsageRequest) (*Reserved, error) { - err := req.Validate() +// Usage gets report resource usage on the resource group +func (r RG) Usage(ctx context.Context, req UsageRequest) (*Reservation, error) { + err := req.validate() if err != nil { return nil, err } @@ -33,12 +40,12 @@ func (r RG) Usage(ctx context.Context, req UsageRequest) (*Reserved, error) { return nil, err } - usage := Reserved{} + info := Reservation{} - err = json.Unmarshal(res, &usage) + err = json.Unmarshal(res, &info) if err != nil { return nil, err } - return &usage, nil + return &info, nil } diff --git a/pkg/cloudbroker/sep.go b/pkg/cloudbroker/sep.go new file mode 100644 index 0000000..29ad412 --- /dev/null +++ b/pkg/cloudbroker/sep.go @@ -0,0 +1,8 @@ +package cloudbroker + +import "github.com/rudecs/decort-sdk/pkg/cloudbroker/sep" + +// Accessing the SEP method group +func (cb *CloudBroker) SEP() *sep.SEP { + return sep.New(cb.client) +} diff --git a/pkg/cloudbroker/sep/access_grant.go b/pkg/cloudbroker/sep/access_grant.go new file mode 100644 index 0000000..e493aef --- /dev/null +++ b/pkg/cloudbroker/sep/access_grant.go @@ -0,0 +1,53 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for grant access to SEP +type AccessGrantRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` + + // Account ID to grant access to the specified SEP. If 0, + // the SEP will be available for all accounts with no exceptions + // Required: true + AccountID uint64 `url:"account_id"` +} + +func (srq AccessGrantRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + if srq.AccountID == 0 { + return errors.New("validation-error: field AccountID must be set") + } + + return nil +} + +// AccessGrant grant access to SEP +func (s SEP) AccessGrant(ctx context.Context, req AccessGrantRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/sep/accessGrant" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/access_grant_to_pool.go b/pkg/cloudbroker/sep/access_grant_to_pool.go new file mode 100644 index 0000000..915f78e --- /dev/null +++ b/pkg/cloudbroker/sep/access_grant_to_pool.go @@ -0,0 +1,60 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for grant access to pool SEP +type AccessGrantToPoolRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` + + // Pool name + // Required: true + PoolName string `url:"pool_name"` + + // Account ID to grant access to the specified pool SEP + // Required: false + AccountID uint64 `url:"account_id,omitempty"` + + // Resource group to grant access to the specified pool SEP + // Required: false + RGID uint64 `url:"resgroup_id,omitempty"` +} + +func (srq AccessGrantToPoolRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + if srq.PoolName == "" { + return errors.New("validation-error: field PoolName must be set") + } + + return nil +} + +// AccessGrantToPool grant access to pool SEP +func (s SEP) AccessGrantToPool(ctx context.Context, req AccessGrantToPoolRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/sep/accessGrantToPool" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/access_revoke.go b/pkg/cloudbroker/sep/access_revoke.go new file mode 100644 index 0000000..62482c4 --- /dev/null +++ b/pkg/cloudbroker/sep/access_revoke.go @@ -0,0 +1,52 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for revoke access to SEP +type AccessRevokeRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` + + // Account ID to revoke access to the specified SEP + // Required: true + AccountID uint64 `url:"account_id"` +} + +func (srq AccessRevokeRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + if srq.AccountID == 0 { + return errors.New("validation-error: field AccountID must be set") + } + + return nil +} + +// AccessRevoke revoke access to SEP +func (s SEP) AccessRevoke(ctx context.Context, req AccessRevokeRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/sep/accessRevoke" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/access_revoke_to_pool.go b/pkg/cloudbroker/sep/access_revoke_to_pool.go new file mode 100644 index 0000000..afdd60a --- /dev/null +++ b/pkg/cloudbroker/sep/access_revoke_to_pool.go @@ -0,0 +1,60 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for revoke access to pool SEP +type AccessRevokeToPoolRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` + + // Pool name + // Required: true + PoolName string `url:"pool_name"` + + // Account ID to grant access to the specified pool SEP + // Required: false + AccountID uint64 `url:"account_id,omitempty"` + + // Resource group ID to grant access to the specified pool SEP + // Required: false + RGID uint64 `url:"resgroup_id,omitempty"` +} + +func (srq AccessRevokeToPoolRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + if srq.PoolName == "" { + return errors.New("validation-error: field PoolName must be set") + } + + return nil +} + +// AccessRevokeToPool revoke access to pool SEP +func (s SEP) AccessRevokeToPool(ctx context.Context, req AccessRevokeToPoolRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/sep/accessRevokeToPool" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/add_consumer_nodes.go b/pkg/cloudbroker/sep/add_consumer_nodes.go new file mode 100644 index 0000000..181229b --- /dev/null +++ b/pkg/cloudbroker/sep/add_consumer_nodes.go @@ -0,0 +1,52 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for add consumer nodes +type AddConsumerNodesRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` + + // List of nodes IDs + // Required: true + ConsumerNIDs []uint64 `url:"consumer_nids"` +} + +func (srq AddConsumerNodesRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + if len(srq.ConsumerNIDs) == 0 { + return errors.New("validation-error: field ConsumerNIDs must be set") + } + + return nil +} + +// AddConsumerNodes add consumer nodes to SEP parameters +func (s SEP) AddConsumerNodes(ctx context.Context, req AddConsumerNodesRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/sep/addConsumerNodes" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/add_provider_nodes.go b/pkg/cloudbroker/sep/add_provider_nodes.go new file mode 100644 index 0000000..81bcafe --- /dev/null +++ b/pkg/cloudbroker/sep/add_provider_nodes.go @@ -0,0 +1,52 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for add provider nodes +type AddProviderNodesRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` + + // List of node IDs + // Required: true + ProviderNIDs []uint64 `url:"provider_nids"` +} + +func (srq AddProviderNodesRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + if len(srq.ProviderNIDs) == 0 { + return errors.New("validation-error: field ProviderNIDs must be set") + } + + return nil +} + +// AddProviderNodes add provider nodes to SEP parameters +func (s SEP) AddProviderNodes(ctx context.Context, req AddProviderNodesRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/sep/addProviderNodes" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/config_field_edit.go b/pkg/cloudbroker/sep/config_field_edit.go new file mode 100644 index 0000000..dbc002e --- /dev/null +++ b/pkg/cloudbroker/sep/config_field_edit.go @@ -0,0 +1,78 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" + + "github.com/rudecs/decort-sdk/internal/validators" +) + +// Request struct for edit config fields +type ConfigFieldEditRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` + + // Field name + // Required: true + FieldName string `url:"field_name"` + + // Field value + // Required: true + FieldValue string `url:"field_value"` + + // Field type + // Should be one of: + // - int + // - str + // - bool + // - list + // - dict + // Required: true + FieldType string `url:"field_type"` +} + +func (srq ConfigFieldEditRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + if srq.FieldName == "" { + return errors.New("validation-error: field FieldName must be set") + } + if srq.FieldValue == "" { + return errors.New("validation-error: field FieldValue must be set") + } + if srq.FieldType == "" { + return errors.New("validation-error: field FieldType must be set") + } + validate := validators.StringInSlice(srq.FieldType, []string{"int", "str", "bool", "list", "dict"}) + if !validate { + return errors.New("validation-error: field FieldType must be one of int, str, bool, list, dict") + } + + return nil +} + +// ConfigFieldEdit edit SEP config field value +func (s SEP) ConfigFieldEdit(ctx context.Context, req ConfigFieldEditRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/sep/configFieldEdit" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/config_insert.go b/pkg/cloudbroker/sep/config_insert.go new file mode 100644 index 0000000..c7f5743 --- /dev/null +++ b/pkg/cloudbroker/sep/config_insert.go @@ -0,0 +1,52 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for insert config +type ConfigInsertRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` + + // Storage provider config + // Required: true + Config string `url:"config"` +} + +func (srq ConfigInsertRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + if srq.Config == "" { + return errors.New("validation-error: feold Config must be set") + } + + return nil +} + +// ConfigInsert insert config to SEP +func (s SEP) ConfigInsert(ctx context.Context, req ConfigInsertRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/sep/configInsert" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/config_validate.go b/pkg/cloudbroker/sep/config_validate.go new file mode 100644 index 0000000..d0463cf --- /dev/null +++ b/pkg/cloudbroker/sep/config_validate.go @@ -0,0 +1,52 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for validate config +type ConfigValidateRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` + + // Storage provider config + // Required: true + Config string `url:"config"` +} + +func (srq ConfigValidateRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + if srq.Config == "" { + return errors.New("validation-error: feold Config must be set") + } + + return nil +} + +// ConfigValidate verify config for the SEP +func (s SEP) ConfigValidate(ctx context.Context, req ConfigValidateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/sep/configValidate" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/consumption.go b/pkg/cloudbroker/sep/consumption.go new file mode 100644 index 0000000..27c98fa --- /dev/null +++ b/pkg/cloudbroker/sep/consumption.go @@ -0,0 +1,47 @@ +package sep + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get consumption info +type ConsumptionRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` +} + +func (srq ConsumptionRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + + return nil +} + +// Consumption get SEP consumption info +func (s SEP) Consumption(ctx context.Context, req ConsumptionRequest) (*RecordConsumption, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/sep/consumption" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + info := RecordConsumption{} + + err = json.Unmarshal(res, &info) + if err != nil { + return nil, err + } + + return &info, nil +} diff --git a/pkg/cloudbroker/sep/create.go b/pkg/cloudbroker/sep/create.go new file mode 100644 index 0000000..f818a77 --- /dev/null +++ b/pkg/cloudbroker/sep/create.go @@ -0,0 +1,79 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for create SEP object +type CreateRequest struct { + // Grid ID + // Required: true + GID uint64 `url:"gid"` + + // SEP name + // Required: true + Name string `url:"name"` + + // Type of storage + // Required: true + SEPType string `url:"sep_type"` + + // Description + // Required: false + Description string `url:"description,omitempty"` + + // SEP config + // Required: false + Config string `url:"config,omitempty"` + + // List of provider node IDs + // Required: false + ProviderNIDs []uint64 `url:"provider_nids,omitempty"` + + // List of consumer node IDs + // Required: false + ConsumerNIDs []uint64 `url:"consumer_nids,omitempty"` + + // Enable SEP after creation + // Required: false + Enable bool `url:"enable,omitempty"` +} + +func (srq CreateRequest) validate() error { + if srq.GID == 0 { + return errors.New("validation-error: field GID must be set") + } + if srq.Name == "" { + return errors.New("validation-error: field Name must be set") + } + if srq.SEPType == "" { + return errors.New("validation-error: field SEPType must be set") + } + + return nil +} + +// Create creates SEP object +func (s SEP) Create(ctx context.Context, req CreateRequest) (uint64, error) { + err := req.validate() + if err != nil { + return 0, err + } + + url := "/cloudbroker/sep/create" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/decommission.go b/pkg/cloudbroker/sep/decommission.go new file mode 100644 index 0000000..5e089f0 --- /dev/null +++ b/pkg/cloudbroker/sep/decommission.go @@ -0,0 +1,49 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for decommission +type DecommissionRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` + + // Clear disks and images physically + // Required: false + ClearPhisically bool `url:"clear_physically,omitempty"` +} + +func (srq DecommissionRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + + return nil +} + +// Decommission unlink everything that exists from SEP +func (s SEP) Decommission(ctx context.Context, req DecommissionRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/sep/decommission" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/del_consumer_nodes.go b/pkg/cloudbroker/sep/del_consumer_nodes.go new file mode 100644 index 0000000..2bd0869 --- /dev/null +++ b/pkg/cloudbroker/sep/del_consumer_nodes.go @@ -0,0 +1,52 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for exclude consumer nodes +type DelConsumerNodesRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` + + // List of consumer node IDs + // Required: true + ConsumerNIDs []uint64 `url:"consumer_nids"` +} + +func (srq DelConsumerNodesRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + if len(srq.ConsumerNIDs) == 0 { + return errors.New("validation-error: field ConsumerNIDs must be set") + } + + return nil +} + +// DelConsumerNodes exclude consumer nodes from SEP parameters +func (s SEP) DelConsumerNodes(ctx context.Context, req DelConsumerNodesRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/sep/delConsumerNodes" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/delete.go b/pkg/cloudbroker/sep/delete.go new file mode 100644 index 0000000..1a18a3e --- /dev/null +++ b/pkg/cloudbroker/sep/delete.go @@ -0,0 +1,45 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete SEP +type DeleteRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` +} + +func (srq DeleteRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + + return nil +} + +// Delete deletes SEP by ID +func (s SEP) Delete(ctx context.Context, req DeleteRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/sep/delete" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/disable.go b/pkg/cloudbroker/sep/disable.go new file mode 100644 index 0000000..bea1a69 --- /dev/null +++ b/pkg/cloudbroker/sep/disable.go @@ -0,0 +1,45 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for disable SEP +type DisableRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` +} + +func (srq DisableRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + + return nil +} + +// Disable disables SEP by ID +func (s SEP) Disable(ctx context.Context, req DisableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/sep/disable" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/disk_list.go b/pkg/cloudbroker/sep/disk_list.go new file mode 100644 index 0000000..c73c9f7 --- /dev/null +++ b/pkg/cloudbroker/sep/disk_list.go @@ -0,0 +1,51 @@ +package sep + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get list of disk IDs +type DiskListRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` + + // Pool name + // Required: false + PoolName string `url:"pool_name,omitempty"` +} + +func (srq DiskListRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + + return nil +} + +// DiskList get list of disk IDs, who use this SEP and pool (if provided) +func (s SEP) DiskList(ctx context.Context, req DiskListRequest) ([]uint64, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/sep/diskList" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := make([]uint64, 0) + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/sep/enable.go b/pkg/cloudbroker/sep/enable.go new file mode 100644 index 0000000..5e6c20d --- /dev/null +++ b/pkg/cloudbroker/sep/enable.go @@ -0,0 +1,45 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for enable SEP +type EnableRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` +} + +func (srq EnableRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + + return nil +} + +// Enable enables SEP by ID +func (s SEP) Enable(ctx context.Context, req EnableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/sep/enable" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sep/get.go b/pkg/cloudbroker/sep/get.go new file mode 100644 index 0000000..121a5ab --- /dev/null +++ b/pkg/cloudbroker/sep/get.go @@ -0,0 +1,47 @@ +package sep + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get SEP parameters +type GetRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` +} + +func (srq GetRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + + return nil +} + +// Get gets SEP parameters +func (s SEP) Get(ctx context.Context, req GetRequest) (*RecordSEP, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/sep/get" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + info := RecordSEP{} + + err = json.Unmarshal(res, &info) + if err != nil { + return nil, err + } + + return &info, nil +} diff --git a/pkg/cloudbroker/sep/get_config.go b/pkg/cloudbroker/sep/get_config.go new file mode 100644 index 0000000..b9792f6 --- /dev/null +++ b/pkg/cloudbroker/sep/get_config.go @@ -0,0 +1,47 @@ +package sep + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get SEP config +type GetConfigRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` +} + +func (srq GetConfigRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + + return nil +} + +// GetConfig gets SEP config +func (s SEP) GetConfig(ctx context.Context, req GetConfigRequest) (*SEPConfig, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/sep/getConfig" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + info := SEPConfig{} + + err = json.Unmarshal(res, &info) + if err != nil { + return nil, err + } + + return &info, nil +} diff --git a/pkg/cloudbroker/sep/get_pool.go b/pkg/cloudbroker/sep/get_pool.go new file mode 100644 index 0000000..85867dc --- /dev/null +++ b/pkg/cloudbroker/sep/get_pool.go @@ -0,0 +1,54 @@ +package sep + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get SEP pool config by name +type GetPoolRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` + + // Pool name + // Required: true + PoolName string `url:"pool_name"` +} + +func (srq GetPoolRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + if srq.PoolName == "" { + return errors.New("validation-error: PoolName must be set") + } + + return nil +} + +// GetPool gets SEP pool config by name +func (s SEP) GetPool(ctx context.Context, req GetPoolRequest) (*RecordPool, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/sep/getPool" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + info := RecordPool{} + + err = json.Unmarshal(res, &info) + if err != nil { + return nil, err + } + + return &info, nil +} diff --git a/pkg/cloudbroker/sep/list.go b/pkg/cloudbroker/sep/list.go new file mode 100644 index 0000000..5d09cda --- /dev/null +++ b/pkg/cloudbroker/sep/list.go @@ -0,0 +1,37 @@ +package sep + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get list of SEPs +type ListRequest struct { + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` +} + +// List gets list of SEPs +func (s SEP) List(ctx context.Context, req ListRequest) (ListSEP, error) { + url := "/cloudbroker/sep/list" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListSEP{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/sep/models.go b/pkg/cloudbroker/sep/models.go new file mode 100644 index 0000000..e8b058c --- /dev/null +++ b/pkg/cloudbroker/sep/models.go @@ -0,0 +1,127 @@ +package sep + +// Total resource information +type Total struct { + // Capacity limit + CapacityLimit uint64 `json:"capacity_limit"` + + // Disk count + DiskCount uint64 `json:"disk_count"` + + // Disk usage + DiskUsage uint64 `json:"disk_usage"` + + // Snapshot count + SnapshotCount uint64 `json:"snapshot_count"` + + // Snapshot usage + SnapshotUsage uint64 `json:"snapshot_usage"` + + // Usage + Usage uint64 `json:"usage"` + + // Usage limit + UsageLimit uint64 `json:"usage_limit"` +} + +// Main information about consumption +type RecordConsumption struct { + // By pool + ByPool map[string]interface{} `json:"byPool"` + + // Total resource information + Total Total `json:"total"` + + // Type + Type string `json:"type"` +} + +// Main information about URI +type ItemURI struct { + // IP + IP string `json:"ip"` + + // Port + Port uint64 `json:"port"` +} + +// List URIs +type ListURIs []ItemURI + +// Detailed information about SEP pool +type RecordPool struct { + // List access account IDs + AccessAccountIDs []uint64 `json:"accessAccountIds"` + + // List access resource group IDs + AccessResGroupIDs []uint64 `json:"accessResGroupIds"` + + // Name + Name string `json:"name"` + + // Page cache ratio + PageCacheRatio uint64 `json:"pagecache_ratio"` + + // Reference ID + ReferenceID string `json:"referenceId"` + + // List types + Types []string `json:"types"` + + // List URIs + URIs ListURIs `json:"uris"` +} + +// SEP config +type SEPConfig map[string]interface{} + +// Detailed information about SEP +type RecordSEP struct { + // CKey + CKey string `json:"_ckey"` + + // Meta + Meta []interface{} `json:"_meta"` + + // Config + Config SEPConfig `json:"config"` + + // Consumed by + ConsumedBy []uint64 `json:"consumedBy"` + + // Description + Description string `json:"desc"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Object status + ObjStatus string `json:"objStatus"` + + // Provided by + ProvidedBy []uint64 `json:"providedBy"` + + // Shared with + SharedWith []uint64 `json:"sharedWith"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Type + Type string `json:"type"` +} + +// List SEPs +type ListSEP []RecordSEP diff --git a/pkg/cloudbroker/sep/sep.go b/pkg/cloudbroker/sep/sep.go new file mode 100644 index 0000000..dfc262e --- /dev/null +++ b/pkg/cloudbroker/sep/sep.go @@ -0,0 +1,18 @@ +// Operator actions for handling interventions on a storage endpoint provider +package sep + +import ( + "github.com/rudecs/decort-sdk/interfaces" +) + +// Structure for creating request to storage endpoint provider +type SEP struct { + client interfaces.Caller +} + +// Builder for SEP endpoints +func New(client interfaces.Caller) *SEP { + return &SEP{ + client: client, + } +} diff --git a/pkg/cloudbroker/sep/update_capacity_limit.go b/pkg/cloudbroker/sep/update_capacity_limit.go new file mode 100644 index 0000000..0228fa4 --- /dev/null +++ b/pkg/cloudbroker/sep/update_capacity_limit.go @@ -0,0 +1,45 @@ +package sep + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for update capacity limits +type UpdateCapacityLimitRequest struct { + // Storage endpoint provider ID + // Required: true + SEPID uint64 `url:"sep_id"` +} + +func (srq UpdateCapacityLimitRequest) validate() error { + if srq.SEPID == 0 { + return errors.New("validation-error: field SEPID must be set") + } + + return nil +} + +// UpdateCapacityLimit updates SEP capacity limit +func (s SEP) UpdateCapacityLimit(ctx context.Context, req UpdateCapacityLimitRequest) (uint64, error) { + err := req.validate() + if err != nil { + return 0, err + } + + url := "/cloudbroker/sep/updateCapacityLimit" + + res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/sizes.go b/pkg/cloudbroker/sizes.go deleted file mode 100644 index 93ad751..0000000 --- a/pkg/cloudbroker/sizes.go +++ /dev/null @@ -1,9 +0,0 @@ -package cloudbroker - -import ( - "github.com/rudecs/decort-sdk/pkg/cloudapi/sizes" -) - -func (cb *CloudBroker) Sizes() *sizes.Sizes { - return sizes.New(cb.client) -} diff --git a/pkg/cloudbroker/tasks.go b/pkg/cloudbroker/tasks.go index 6b1d392..8af8925 100644 --- a/pkg/cloudbroker/tasks.go +++ b/pkg/cloudbroker/tasks.go @@ -1,9 +1,10 @@ package cloudbroker import ( - "github.com/rudecs/decort-sdk/pkg/cloudapi/tasks" + "github.com/rudecs/decort-sdk/pkg/cloudbroker/tasks" ) +// Accessing the tasks method group func (cb *CloudBroker) Tasks() *tasks.Tasks { return tasks.New(cb.client) } diff --git a/pkg/cloudbroker/tasks/get.go b/pkg/cloudbroker/tasks/get.go new file mode 100644 index 0000000..3c60cee --- /dev/null +++ b/pkg/cloudbroker/tasks/get.go @@ -0,0 +1,47 @@ +package tasks + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get background API task status and result +type GetRequest struct { + // ID of audit GUID + // Required: true + AuditID string `url:"auditId"` +} + +func (trq GetRequest) validate() error { + if trq.AuditID == "" { + return errors.New("validation-error: field AuditID must be set") + } + + return nil +} + +// Get gets background API task status and result +func (t Tasks) Get(ctx context.Context, req GetRequest) (*RecordTask, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/tasks/get" + + res, err := t.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + item := RecordTask{} + + err = json.Unmarshal(res, &item) + if err != nil { + return nil, err + } + + return &item, nil +} diff --git a/pkg/cloudbroker/tasks/list.go b/pkg/cloudbroker/tasks/list.go new file mode 100644 index 0000000..a853515 --- /dev/null +++ b/pkg/cloudbroker/tasks/list.go @@ -0,0 +1,37 @@ +package tasks + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get list audits +type ListRequest struct { + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} + +// List gets list user API task with status PROCESSING +func (t Tasks) List(ctx context.Context, req ListRequest) (ListTasks, error) { + url := "/cloudbroker/tasks/list" + + res, err := t.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + item := ListTasks{} + + err = json.Unmarshal(res, &item) + if err != nil { + return nil, err + } + + return item, nil +} diff --git a/pkg/cloudbroker/tasks/models.go b/pkg/cloudbroker/tasks/models.go new file mode 100644 index 0000000..a8a6ac0 --- /dev/null +++ b/pkg/cloudbroker/tasks/models.go @@ -0,0 +1,71 @@ +package tasks + +import ( + "encoding/json" + "fmt" + "strconv" +) + +// Global variable for converting field to desired data type +type InfoResult int + +// Method for convert field +func (r *InfoResult) UnmarshalJSON(b []byte) error { + if b[0] == '"' { + b := b[1 : len(b)-1] + if len(b) == 0 { + *r = 0 + return nil + } + n, err := strconv.Atoi(string(b)) + if err != nil { + return err + } + *r = InfoResult(n) + } else if b[0] == '[' { + res := []interface{}{} + if err := json.Unmarshal(b, &res); err != nil { + return err + } + if n, ok := res[0].(float64); ok { + *r = InfoResult(n) + } else { + return fmt.Errorf("could not unmarshal %v into int", res[0]) + } + } + + return nil +} + +// Detailed information about task +type RecordTask struct { + // Audit ID + AuditID string `json:"auditId"` + + // Completed + Completed bool `json:"completed"` + + // Error + Error string `json:"error"` + + // List of logs + Log []string `json:"log"` + + // Final result + Result InfoResult `json:"result"` + + // Stage + Stage string `json:"stage"` + + // Status + Status string `json:"status"` + + // Update time + UpdateTime uint64 `json:"updateTime"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` +} + +// List of tasks +type ListTasks []RecordTask diff --git a/pkg/cloudbroker/tasks/tasks.go b/pkg/cloudbroker/tasks/tasks.go new file mode 100644 index 0000000..8466d7b --- /dev/null +++ b/pkg/cloudbroker/tasks/tasks.go @@ -0,0 +1,16 @@ +// User API tasks interface +package tasks + +import "github.com/rudecs/decort-sdk/interfaces" + +// Structure for creating request to tasks +type Tasks struct { + client interfaces.Caller +} + +// Builder for tasks endpoints +func New(client interfaces.Caller) *Tasks { + return &Tasks{ + client: client, + } +} diff --git a/pkg/cloudbroker/vins.go b/pkg/cloudbroker/vins.go index 5e2b45e..dc84337 100644 --- a/pkg/cloudbroker/vins.go +++ b/pkg/cloudbroker/vins.go @@ -1,9 +1,10 @@ package cloudbroker import ( - "github.com/rudecs/decort-sdk/pkg/cloudapi/vins" + "github.com/rudecs/decort-sdk/pkg/cloudbroker/vins" ) +// Accessing the VINS method group func (cb *CloudBroker) VINS() *vins.VINS { return vins.New(cb.client) } diff --git a/pkg/cloudbroker/vins/audits.go b/pkg/cloudbroker/vins/audits.go new file mode 100644 index 0000000..009071c --- /dev/null +++ b/pkg/cloudbroker/vins/audits.go @@ -0,0 +1,47 @@ +package vins + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get audits +type AuditsRequest struct { + // ID of the VINS + // Required: true + VINSID uint64 `url:"vinsId"` +} + +func (vrq AuditsRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + + return nil +} + +// Audits gets audit records for the specified VINS object +func (v VINS) Audits(ctx context.Context, req AuditsRequest) (ListAudits, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/vins/audits" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListAudits{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/vins/create_in_account.go b/pkg/cloudbroker/vins/create_in_account.go new file mode 100644 index 0000000..169af70 --- /dev/null +++ b/pkg/cloudbroker/vins/create_in_account.go @@ -0,0 +1,72 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for create VINS in account +type CreateInAccountRequest struct { + // VINS name + // Required: true + Name string `url:"name"` + + // ID of account + // Required: true + AccountID uint64 `url:"accountId"` + + // Grid ID + // Required: false + GID uint64 `url:"gid,omitempty"` + + // Private network IP CIDR + // Required: false + IPCIDR string `url:"ipcidr,omitempty"` + + // Description + // Required: false + Description string `url:"desc,omitempty"` + + // Number of pre created reservations + // Required: false + PreReservationsNum uint64 `url:"preReservationsNum,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq CreateInAccountRequest) validate() error { + if vrq.Name == "" { + return errors.New("validation-error: field Name must be set") + } + if vrq.AccountID == 0 { + return errors.New("validation-error: field AccountID must be set") + } + + return nil +} + +// CreateInAccount creates VINS in account level +func (v VINS) CreateInAccount(ctx context.Context, req CreateInAccountRequest) (uint64, error) { + err := req.validate() + if err != nil { + return 0, err + } + + url := "/cloudbroker/vins/createInAccount" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/create_in_rg.go b/pkg/cloudbroker/vins/create_in_rg.go new file mode 100644 index 0000000..47193a9 --- /dev/null +++ b/pkg/cloudbroker/vins/create_in_rg.go @@ -0,0 +1,76 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for create VINS in resource group +type CreateInRGRequest struct { + // VINS name + // Required: true + Name string `url:"name"` + + // Resource group ID + // Required: true + RGID uint64 `url:"rgId"` + + // Private network IP CIDR + // Required: false + IPCIDR string `url:"ipcidr,omitempty"` + + // External network ID + // Required: false + ExtNetID uint64 `url:"extNetId,omitempty"` + + // External IP, related only for extNetId >= 0 + // Required: false + ExtIP string `url:"extIp,omitempty"` + + // Description + // Required: false + Description string `url:"desc,omitempty"` + + // Number of pre created reservations + // Required: false + PreReservationsNum uint `url:"preReservationsNum,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq CreateInRGRequest) validate() error { + if vrq.Name == "" { + return errors.New("validation-error: field Name must be set") + } + if vrq.RGID == 0 { + return errors.New("validation-error: field RGID must be set") + } + + return nil +} + +// CreateInRG creates VINS in resource group level +func (v VINS) CreateInRG(ctx context.Context, req CreateInRGRequest) (uint64, error) { + err := req.validate() + if err != nil { + return 0, err + } + + url := "/cloudbroker/vins/createInRG" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/default_qos_update.go b/pkg/cloudbroker/vins/default_qos_update.go new file mode 100644 index 0000000..63b457c --- /dev/null +++ b/pkg/cloudbroker/vins/default_qos_update.go @@ -0,0 +1,57 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for update QOS +type DefaultQOSUpdateRequest struct { + // ID of VINS + // Required: true + VINSID uint64 `url:"vinsId"` + + // Internal traffic, kbit + // Required: false + IngressRate uint64 `url:"ingress_rate,omitempty"` + + // Internal traffic burst, kbit + // Required: false + IngressBirst uint64 `url:"ingress_birst,omitempty"` + + // External traffic rate, kbit + // Required: false + EgressRate uint64 `url:"egress_rate,omitempty"` +} + +func (vrq DefaultQOSUpdateRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + + return nil +} + +// DefaultQOSUpdate update default QOS values +func (v VINS) DefaultQOSUpdate(ctx context.Context, req DefaultQOSUpdateRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/defaultQosUpdate" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/delete.go b/pkg/cloudbroker/vins/delete.go new file mode 100644 index 0000000..4d5ff62 --- /dev/null +++ b/pkg/cloudbroker/vins/delete.go @@ -0,0 +1,61 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete VINS +type DeleteRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Set to True if you want force delete non-empty VINS. + // Primarily, VINS is considered non-empty if it has virtual machines connected to it, + // and force flag will detach them from the VINS being deleted. + // Otherwise method will return an error + // Required: false + Force bool `url:"force,omitempty"` + + // Set to True if you want to destroy VINS and all linked resources, if any, immediately. + // Otherwise, they will be placed into recycle bin and could be restored later within the recycle bin's purge period + // Required: false + Permanently bool `url:"permanently,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq DeleteRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + + return nil +} + +// Delete deletes VINS +func (v VINS) Delete(ctx context.Context, req DeleteRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/delete" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/disable.go b/pkg/cloudbroker/vins/disable.go new file mode 100644 index 0000000..12a5770 --- /dev/null +++ b/pkg/cloudbroker/vins/disable.go @@ -0,0 +1,49 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for disable VINS +type DisableRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq DisableRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + + return nil +} + +// Disable disables VINS by ID +func (v VINS) Disable(ctx context.Context, req DisableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/disable" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/enable.go b/pkg/cloudbroker/vins/enable.go new file mode 100644 index 0000000..f4e0500 --- /dev/null +++ b/pkg/cloudbroker/vins/enable.go @@ -0,0 +1,49 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for enable VINS +type EnableRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq EnableRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + + return nil +} + +// Enable enables VINS by ID +func (v VINS) Enable(ctx context.Context, req EnableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/enable" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/extnet_connect.go b/pkg/cloudbroker/vins/extnet_connect.go new file mode 100644 index 0000000..09b9286 --- /dev/null +++ b/pkg/cloudbroker/vins/extnet_connect.go @@ -0,0 +1,60 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for connect external network +type ExtNetConnectRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // External network ID + // Required: true + NetID uint64 `url:"netId"` + + // Directly set IP address + // Required: false + IP string `url:"ip,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq ExtNetConnectRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + if vrq.NetID == 0 { + return errors.New("validation-error: field NetID must be set") + } + + return nil +} + +// ExtNetConnect connect VINS to external network +func (v VINS) ExtNetConnect(ctx context.Context, req ExtNetConnectRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/extNetConnect" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/extnet_disconnect.go b/pkg/cloudbroker/vins/extnet_disconnect.go new file mode 100644 index 0000000..bc2bef3 --- /dev/null +++ b/pkg/cloudbroker/vins/extnet_disconnect.go @@ -0,0 +1,49 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for disconnect VINS from external network +type ExtNetDisconnectRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq ExtNetDisconnectRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + + return nil +} + +// ExtNetDisconnect disconnect VINS from external network +func (v VINS) ExtNetDisconnect(ctx context.Context, req ExtNetDisconnectRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/extNetDisconnect" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/extnet_list.go b/pkg/cloudbroker/vins/extnet_list.go new file mode 100644 index 0000000..9fd8b66 --- /dev/null +++ b/pkg/cloudbroker/vins/extnet_list.go @@ -0,0 +1,51 @@ +package vins + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get list VINS external network connections +type ExtNetListRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq ExtNetListRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + + return nil +} + +// ExtNetList show list of VINS external network connections +func (v VINS) ExtNetList(ctx context.Context, req ExtNetListRequest) (ListExtNets, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/vins/extNetList" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListExtNets{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/vins/get.go b/pkg/cloudbroker/vins/get.go new file mode 100644 index 0000000..ec6ca98 --- /dev/null +++ b/pkg/cloudbroker/vins/get.go @@ -0,0 +1,51 @@ +package vins + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get information about VINS +type GetRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq GetRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + + return nil +} + +// Get gets information about VINS by ID +func (v VINS) Get(ctx context.Context, req GetRequest) (*RecordVINS, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/vins/get" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + info := RecordVINS{} + + err = json.Unmarshal(res, &info) + if err != nil { + return nil, err + } + + return &info, nil +} diff --git a/pkg/cloudbroker/vins/ip_list.go b/pkg/cloudbroker/vins/ip_list.go new file mode 100644 index 0000000..9502c54 --- /dev/null +++ b/pkg/cloudbroker/vins/ip_list.go @@ -0,0 +1,47 @@ +package vins + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for DHCP IP +type IPListRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` +} + +func (vrq IPListRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + + return nil +} + +// IPList show DHCP IP reservations on VINS +func (v VINS) IPList(ctx context.Context, req IPListRequest) (ListIPs, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/vins/ipList" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListIPs{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/vins/ip_release.go b/pkg/cloudbroker/vins/ip_release.go new file mode 100644 index 0000000..52b5624 --- /dev/null +++ b/pkg/cloudbroker/vins/ip_release.go @@ -0,0 +1,54 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for IP relese +type IPReleaseRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // IP address + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // MAC address + // Required: false + MAC string `url:"mac,omitempty"` +} + +func (vrq IPReleaseRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + + return nil +} + +// IPRelese delete IP reservation matched by specified IP & MAC address combination. +// If both IP and MAC address are empty strings, all IP reservations will be deleted. +func (v VINS) IPRelease(ctx context.Context, req IPReleaseRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/ipRelease" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/ip_reserve.go b/pkg/cloudbroker/vins/ip_reserve.go new file mode 100644 index 0000000..44a2d2e --- /dev/null +++ b/pkg/cloudbroker/vins/ip_reserve.go @@ -0,0 +1,79 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strings" + + "github.com/rudecs/decort-sdk/internal/validators" +) + +// Request struct for IP reserve +type IPReserveRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Type of the reservation + // Should be one of: + // - DHCP + // - VIP + // - EXCLUDE + // Required: true + Type string `url:"type"` + + // IP address to use. Non-empty string is required for type "EXCLUDE". + // Ignored for types "DHCP" and "VIP". + // Required: false + IPAddr string `url:"ipAddr,omitempty"` + + // MAC address to associate with IP reservation. + // Ignored for type "EXCLUDE", + // non-empty string is required for "DHCP" and "VIP" + // Required: false + MAC string `url:"mac,omitempty"` + + // ID of the compute, associated with this reservation of type "DHCP". + // Ignored for other types + // Required: false + ComputeID uint64 `url:"computeId,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq IPReserveRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + if vrq.Type == "" { + return errors.New("validation-error: field Type must be set") + } + validate := validators.StringInSlice(vrq.Type, []string{"DHCP", "VIP", "EXCLUDED"}) + if !validate { + return errors.New("'type' should be 'DHCP', 'VIP' or 'EXCLUDED'") + } + + return nil +} + +// IPReserve creates reservation on ViNS DHCP +func (v VINS) IPReserve(ctx context.Context, req IPReserveRequest) (string, error) { + err := req.validate() + if err != nil { + return "", err + } + + url := "/cloudbroker/vins/ipReserve" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + result := strings.ReplaceAll(string(res), "\"", "") + + return result, nil +} diff --git a/pkg/cloudbroker/vins/list.go b/pkg/cloudbroker/vins/list.go new file mode 100644 index 0000000..fd46089 --- /dev/null +++ b/pkg/cloudbroker/vins/list.go @@ -0,0 +1,37 @@ +package vins + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get list of VINSes +type ListRequest struct { + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} + +// List gets list of VINSes +func (v VINS) List(ctx context.Context, req ListRequest) (ListVINS, error) { + url := "/cloudbroker/vins/list" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListVINS{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/vins/list_deleted.go b/pkg/cloudbroker/vins/list_deleted.go new file mode 100644 index 0000000..0a7db50 --- /dev/null +++ b/pkg/cloudbroker/vins/list_deleted.go @@ -0,0 +1,37 @@ +package vins + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get list of deleted VINSes +type ListDeletedRequest struct { + // Page number + // Required: false + Page uint64 `url:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty"` +} + +// ListDeleted gets list of deleted VINSes +func (v VINS) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListVINS, error) { + url := "/cloudbroker/vins/listDeleted" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListVINS{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/vins/mass_delete.go b/pkg/cloudbroker/vins/mass_delete.go new file mode 100644 index 0000000..129e7c5 --- /dev/null +++ b/pkg/cloudbroker/vins/mass_delete.go @@ -0,0 +1,56 @@ +package vins + +import ( + "context" + "errors" + "net/http" +) + +// Request struct for delete several VINSes +type MassDeleteRequest struct { + // VINS IDs + // Required: true + VINSIDs []uint64 `url:"vinsIds"` + + // Set to true if you want force delete non-empty VINS. Primarily, + // VINS is considered non-empty if it has VMs connected to it, + // and force flag will detach them from the VINS being deleted. + // Otherwise method will return an error + // Required: false + Force bool `url:"force,omitempty"` + + // Set to true if you want to destroy VINS and all linked resources, if any, immediately. + // Otherwise, they will be placed into recycle bin and could be restored later + // within the recycle bins purge period + // Required: false + Permanently bool `url:"permanently,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq MassDeleteRequest) validate() error { + if len(vrq.VINSIDs) == 0 { + return errors.New("validation-error: field VINSIDs must be set") + } + + return nil +} + +// MassDelete start jobs to delete several VINSes +func (v VINS) MassDelete(ctx context.Context, req MassDeleteRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/massDelete" + + _, err = v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + return true, nil +} diff --git a/pkg/cloudbroker/vins/mass_disable.go b/pkg/cloudbroker/vins/mass_disable.go new file mode 100644 index 0000000..2f5db84 --- /dev/null +++ b/pkg/cloudbroker/vins/mass_disable.go @@ -0,0 +1,43 @@ +package vins + +import ( + "context" + "errors" + "net/http" +) + +// Request struct for disable several VINSes +type MassDisableRequest struct { + // VINS IDs + // Required: true + VINSIDs []uint64 `url:"vinsIds"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq MassDisableRequest) validate() error { + if len(vrq.VINSIDs) == 0 { + return errors.New("validation-error: field VINSIDs must be set") + } + + return nil +} + +// MassDisable start jobs to disable several VINSes +func (v VINS) MassDisable(ctx context.Context, req MassDisableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/massDisable" + + _, err = v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + return true, nil +} diff --git a/pkg/cloudbroker/vins/mass_enable.go b/pkg/cloudbroker/vins/mass_enable.go new file mode 100644 index 0000000..38e2e19 --- /dev/null +++ b/pkg/cloudbroker/vins/mass_enable.go @@ -0,0 +1,43 @@ +package vins + +import ( + "context" + "errors" + "net/http" +) + +// Request struct for enable several VINSes +type MassEnableRequest struct { + // VINS IDs + // Required: true + VINSIDs []uint64 `url:"vinsIds"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq MassEnableRequest) validate() error { + if len(vrq.VINSIDs) == 0 { + return errors.New("validation-error: field VINSIDs must be set") + } + + return nil +} + +// MassEnable start jobs to enable several VINSes +func (v VINS) MassEnable(ctx context.Context, req MassEnableRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/massEnable" + + _, err = v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + return true, nil +} diff --git a/pkg/cloudbroker/vins/models.go b/pkg/cloudbroker/vins/models.go new file mode 100644 index 0000000..8b5a03b --- /dev/null +++ b/pkg/cloudbroker/vins/models.go @@ -0,0 +1,673 @@ +package vins + +// Main information about audit +type ItemAudit struct { + // Call + Call string `json:"call"` + + // Response time + ResponseTime float64 `json:"responsetime"` + + // Status code + StatusCode uint64 `json:"statuscode"` + + // Timestamp + Timestamp float64 `json:"timestamp"` + + // User + User string `json:"user"` +} + +// List of audits +type ListAudits []ItemAudit + +// Main information about external network +type ItemExtNet struct { + // Default GW + DefaultGW string `json:"default_gw"` + + // External network ID + ExtNetID uint64 `json:"ext_net_id"` + + // IP + IP string `json:"ip"` + + // Prefix len + PrefixLen uint64 `json:"prefixlen"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` +} + +// List of external networks +type ListExtNets []ItemExtNet + +// MGMT +type MGMT struct { + // IP address + IPAddress string `json:"ipaddr"` + + // Password + Password string `json:"password"` + + // SSH key + SSHKey string `json:"sshkey"` + + // User + User string `json:"user"` +} + +// Main information about resource +type Resources struct { + // Number of CPU + CPU uint64 `json:"cpu"` + + // Number of RAM + RAM uint64 `json:"ram"` + + // Stack ID + StackID uint64 `json:"stackId"` + + // UUID + UUID string `json:"uuid"` +} + +// VNF config +type Config struct { + // MGMT + MGMT MGMT `json:"mgmt"` + + // Resources + Resources Resources `json:"resources"` +} + +// Main information about QOS +type QOS struct { + // ERate + ERate uint64 `json:"eRate"` + + // GUID + GUID string `json:"guid"` + + // InBurst + InBurst uint64 `json:"inBurst"` + + // InRate + InRate uint64 `json:"inRate"` +} + +// Main information about interface +type ItemInterface struct { + // Connection ID + ConnID uint64 `json:"connId"` + + // Connection type + ConnType string `json:"connType"` + + // Default GW + DefGW string `json:"defGw"` + + // FLIPGroup ID + FLIPGroupID uint64 `json:"flipgroupId"` + + // GUID + GUID string `json:"guid"` + + // IP address + IPAddress string `json:"ipAddress"` + + // Listen SSH + ListenSSH bool `json:"listenSsh"` + + // MAC + MAC string `json:"mac"` + + // Name + Name string `json:"name"` + + // Network type + NetID uint64 `json:"netId"` + + // Network mask + NetMask uint64 `json:"netMask"` + + // Network type + NetType string `json:"netType"` + + // PCI slot + PCISlot uint64 `json:"pciSlot"` + + // QOS + QOS QOS `json:"qos"` + + // Target + Target string `json:"target"` + + // Type + Type string `json:"type"` + + // List of VNF IDs + VNFs []uint64 `json:"vnfs"` +} + +// List of interfaces +type ListInterfaces []ItemInterface + +// Main information about VNF device +type VNFDev struct { + // CKey + CKey string `json:"_ckey"` + + // Meta + Meta []interface{} `json:"_meta"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Capabilities + Capabilities []string `json:"capabilities"` + + // Config + Config Config `json:"config"` + + // Config saved + ConfigSaved bool `json:"configSaved"` + + // CustomPreConfig + CustomPreConfig bool `json:"customPrecfg"` + + // Description + Description string `json:"desc"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // List of interfaces + Interfaces ListInterfaces `json:"interfaces"` + + // Lock status + LockStatus string `json:"lockStatus"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Status + Status string `json:"status"` + + // TechStatus + TechStatus string `json:"techStatus"` + + // Type + Type string `json:"type"` + + //List of VINS IDs + VINS []uint64 `json:"vins"` +} + +// Main information about reservation +type ItemReservation struct { + // Client type + ClientType string `json:"clientType"` + + // Description + Description string `json:"desc"` + + // Domain name + DomainName string `json:"domainname"` + + // Hostname + Hostname string `json:"hostname"` + + // IP + IP string `json:"ip"` + + // MAC + MAC string `json:"mac"` + + // Type + Type string `json:"type"` + + // Virtual machine ID + VMID uint64 `json:"vmId"` +} + +// List of reservations +type ListReservations []ItemReservation + +// VNFs sonfig +type VNFsConfig struct { + // Default GW + DefaultGW string `json:"default_gw"` + + // List of DNS + DNS []string `json:"dns"` + + // IP end + IPEnd string `json:"ip_end"` + + // IP start + IPStart string `json:"ip_start"` + + // Lease + Lease uint64 `json:"lease"` + + // Network mask + NetMask uint64 `json:"netmask"` + + // Network + Network string `json:"network"` + + // List of reservations + Reservations ListReservations `json:"reservations"` +} + +// Primary +type Primary struct { + // Device ID + DevID uint64 `json:"devId"` + + // IFace01 + IFace01 string `json:"iface01"` + + // IFace02 + IFace02 string `json:"iface02"` +} + +// Devices +type Devices struct { + // Primary + Primary Primary `json:"primary"` +} + +// Main information about DHCP +type RecordDHCP struct { + // Config + Config VNFsConfig `json:"config"` + + // DHCP details + InfoVNF +} + +// GW config +type GWConfig struct { + // Default GW + DefaultGW string `json:"default_gw"` + + // External network ID + ExtNetID uint64 `json:"ext_net_id"` + + // External network IP + ExtNetIP string `json:"ext_net_ip"` + + // External network mask + ExtNetMask uint64 `json:"ext_netmask"` + + // QOS + QOS QOS `json:"qos"` +} + +// Main information about GW +type RecordGW struct { + // Config + Config GWConfig `json:"config"` + + // GW details + InfoVNF +} + +// NAT config +type NATConfig struct { + // Network mask + NetMask uint64 `json:"netmask"` + + // Network + Network string `json:"network"` + + // Rules + Rules []interface{} `json:"rules"` +} + +// Main information about NAT +type RecordNAT struct { + // Config + Config NATConfig `json:"config"` + + // NAT details + InfoVNF +} + +// NAT/GW/NAT details +type InfoVNF struct { + // CKey + CKey string `json:"_ckey"` + + // Meta + Meta []interface{} `json:"_meta"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Config + Config NATConfig `json:"config"` + + // CreatedTime + CreatedTime uint64 `json:"createdTime"` + + // Devices + Devices Devices `json:"devices"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Lock status + LockStatus string `json:"lockStatus"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Owner ID + OwnerID uint64 `json:"ownerId"` + + // Owner type + OwnerType string `json:"ownerType"` + + // Pure virtual + PureVirtual bool `json:"pureVirtual"` + + // Status + Status string `json:"status"` + + // Tech status + TechStatus string `json:"techStatus"` + + // Type + Type string `json:"type"` +} + +// main information about VNF +type RecordVNFs struct { + // DHCP + DHCP RecordDHCP `json:"DHCP"` + + // GW + GW RecordGW `json:"GW"` + + // NAT + NAT RecordNAT `json:"NAT"` +} + +// Detailed information about VINS +type RecordVINS struct { + // VNF device + VNFDev VNFDev `json:"VNFDev"` + + // CKey + CKey string `json:"_ckey"` + + // Meta + Meta []interface{} `json:"_meta"` + + // Account ID + AccountID uint64 `json:"accountId"` + + // Default GW + DefaultGW string `json:"defaultGW"` + + // Default QOS + DefaultQOS QOS `json:"defaultQos"` + + // Description + Description string `json:"desc"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Lock status + LockStatus string `json:"lockStatus"` + + // Manager ID + ManagerID uint64 `json:"managerId"` + + // Manager type + ManagerType string `json:"managerType"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Network mask + NetMask uint64 `json:"netMask"` + + // Network + Network string `json:"network"` + + // PreReservationsNum + PreReservationsNum uint64 `json:"preReservationsNum"` + + // Redundant + Redundant bool `json:"redundant"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // SecVNFDevID + SecVNFDevID uint64 `json:"secVnfDevId"` + + // Status + Status string `json:"status"` + + // User managed + UserManaged bool `json:"userManaged"` + + // VNFs information + VNFs RecordVNFs `json:"vnfs"` + + // VXLAN ID + VXLANID uint64 `json:"vxlanId"` +} + +// Main information about IP +type ItemIP struct { + // IP + IP string `json:"ip"` + + // MAC + MAC string `json:"mac"` + + // Type + Type string `json:"type"` + + // Virtual machine ID + VMID uint64 `json:"vmId"` + + // Client type + ClientType string `json:"clientType"` + + // Domain name + DomainName string `json:"domainname"` + + // Hostname + Hostname string `json:"hostname"` +} + +// List of information about IPs +type ListIPs []ItemIP + +// Main information about NAT rule +type ItemNATRule struct { + // ID + ID uint64 `json:"id"` + + // Local IP + LocalIP string `json:"localIp"` + + // Local port + LocalPort uint64 `json:"localPort"` + + // Protocol + Protocol string `json:"protocol"` + + // Public port end + PublicPortEnd uint64 `json:"publicPortEnd"` + + // Public port start + PublicPortStart uint64 `json:"publicPortStart"` + + // Virtual machine ID + VMID uint64 `json:"vmId"` + + // Virtual machine name + VMName string `json:"vmName"` +} + +// List NAT rules +type ListNATRules []ItemNATRule + +// Shorted information about VNF +type ItemVNFs struct { + // DHCP + DHCP uint64 `json:"dhcp"` + + // DNS + DNS uint64 `json:"dns"` + + // FW + FW uint64 `json:"fw"` + + // GW + GW uint64 `json:"gw"` + + // NAT + NAT uint64 `json:"nat"` + + // VPN + VPN uint64 `json:"vpn"` +} + +// Main information about VINS +type ItemVINS struct { + // Account ID + AccountID uint64 `json:"accountId"` + + // Account name + AccountName string `json:"accountName"` + + // Created by + CreatedBy string `json:"createdBy"` + + // Created time + CreatedTime uint64 `json:"createdTime"` + + // Default GW + DefaultGW string `json:"defaultGW"` + + // Default QOS + DefaultQOS QOS `json:"defaultQos"` + + // Deleted by + DeletedBy string `json:"deletedBy"` + + // Deleted time + DeletedTime uint64 `json:"deletedTime"` + + // Description + Description string `json:"desc"` + + // External IP + ExternalIP string `json:"externalIP"` + + // Grid ID + GID uint64 `json:"gid"` + + // GUID + GUID uint64 `json:"guid"` + + // ID + ID uint64 `json:"id"` + + // Lock status + LockStatus string `json:"lockStatus"` + + // Manager ID + ManagerID uint64 `json:"managerId"` + + // Manager type + ManagerType string `json:"managerType"` + + // Milestones + Milestones uint64 `json:"milestones"` + + // Name + Name string `json:"name"` + + // Network mask + NetMask uint64 `json:"netMask"` + + // Network + Network string `json:"network"` + + // PreReservationsNum + PreReservationsNum uint64 `json:"preReservationsNum"` + + // PriVNFDevID + PriVNFDevID uint64 `json:"priVnfDevId"` + + // Redundant + Redundant bool `json:"redundant"` + + // Resource group ID + RGID uint64 `json:"rgId"` + + // Resource group name + RGName string `json:"rgName"` + + // SecVNFDevID + SecVNFDevID uint64 `json:"secVnfDevId"` + + // Status + Status string `json:"status"` + + // Updated by + UpdatedBy string `json:"updatedBy"` + + // Updated time + UpdatedTime uint64 `json:"updatedTime"` + + // User managed + UserManaged bool `json:"userManaged"` + + // VNFs + VNFs ItemVNFs `json:"vnfs"` + + // VXLAN ID + VXLANID uint64 `json:"vxlanId"` +} + +// List of VINS +type ListVINS []ItemVINS diff --git a/pkg/cloudbroker/vins/nat_rule_add.go b/pkg/cloudbroker/vins/nat_rule_add.go new file mode 100644 index 0000000..8bf902c --- /dev/null +++ b/pkg/cloudbroker/vins/nat_rule_add.go @@ -0,0 +1,81 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for create NAT rules +type NATRuleAddRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Internal IP address to apply this rule to + // Required: true + IntIP string `url:"intIp "` + + // Internal IP port number to use for this rule + // Required: true + IntPort uint `url:"intPort"` + + // External IP start port to use for this rule + // Required: true + ExtPortStart uint `url:"extPortStart"` + + // External IP end port to use for this rule + // Required: false + ExtPortEnd uint `url:"extPortEnd,omitempty"` + + // IP protocol type + // Should be one of: + // - "tcp" + // - "udp" + // Required: false + Proto string `url:"proto,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq NATRuleAddRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + if vrq.IntIP == "" { + return errors.New("validation-error: field IntIP must be set") + } + if vrq.IntPort == 0 { + return errors.New("validation-error: field IntPort must be set") + } + if vrq.ExtPortStart == 0 { + return errors.New("validation-error: field ExtPortStart must be set") + } + + return nil +} + +// NATRuleAdd create NAT (port forwarding) rule on VINS +func (v VINS) NATRuleAdd(ctx context.Context, req NATRuleAddRequest) (uint64, error) { + err := req.validate() + if err != nil { + return 0, err + } + + url := "/cloudbroker/vins/natRuleAdd" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/nat_rule_del.go b/pkg/cloudbroker/vins/nat_rule_del.go new file mode 100644 index 0000000..7eccb7e --- /dev/null +++ b/pkg/cloudbroker/vins/nat_rule_del.go @@ -0,0 +1,57 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for delete NAT rule +type NATRuleDelRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // ID of the rule to delete. + // Pass -1 to clear all rules at once + // Required: true + RuleID uint64 `url:"ruleId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq NATRuleDelRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + if vrq.RuleID == 0 { + return errors.New("validation-error: field RuleID must be set") + } + + return nil +} + +// NATRuleDel delete NAT (port forwarding) rule on VINS +func (v VINS) NATRuleDel(ctx context.Context, req NATRuleDelRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/natRuleDel" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/nat_rule_list.go b/pkg/cloudbroker/vins/nat_rule_list.go new file mode 100644 index 0000000..34131be --- /dev/null +++ b/pkg/cloudbroker/vins/nat_rule_list.go @@ -0,0 +1,51 @@ +package vins + +import ( + "context" + "encoding/json" + "errors" + "net/http" +) + +// Request struct for get list of NAT rules +type NATRuleListRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq NATRuleListRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + + return nil +} + +// NATRuleList gets list of NAT (port forwarding) rules +func (v VINS) NATRuleList(ctx context.Context, req NATRuleListRequest) (ListNATRules, error) { + err := req.validate() + if err != nil { + return nil, err + } + + url := "/cloudbroker/vins/natRuleList" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListNATRules{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/vins/net_qos.go b/pkg/cloudbroker/vins/net_qos.go new file mode 100644 index 0000000..000c29a --- /dev/null +++ b/pkg/cloudbroker/vins/net_qos.go @@ -0,0 +1,57 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for update all VINS interfaces QOS +type NetQOSRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Internal traffic, kbit + // Required: false + IngressRate uint64 `url:"ingress_rate,omitempty"` + + // Internal traffic burst, kbit + // Required: false + IngressBirst uint64 `url:"ingress_birst,omitempty"` + + // External traffic rate, kbit + // Required: false + EgressRate uint64 `url:"egress_rate,omitempty"` +} + +func (vrq NetQOSRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + + return nil +} + +// NetQOS update all VINS interfaces QOS +func (v VINS) NetQOS(ctx context.Context, req NetQOSRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/netQos" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/raise_down.go b/pkg/cloudbroker/vins/raise_down.go new file mode 100644 index 0000000..416c627 --- /dev/null +++ b/pkg/cloudbroker/vins/raise_down.go @@ -0,0 +1,24 @@ +package vins + +import ( + "context" + "net/http" + "strconv" +) + +// RaiseDown starting all VINSes VNFDevs in "DOWN" tech status +func (v VINS) RaiseDown(ctx context.Context) (bool, error) { + url := "/cloudbroker/vins/raiseDown" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, nil) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/restore.go b/pkg/cloudbroker/vins/restore.go new file mode 100644 index 0000000..42c47a8 --- /dev/null +++ b/pkg/cloudbroker/vins/restore.go @@ -0,0 +1,49 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for restore +type RestoreRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq RestoreRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: field VINSID must be set") + } + + return nil +} + +// Restore restores VINS from recycle bin +func (v VINS) Restore(ctx context.Context, req RestoreRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/restore" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/search.go b/pkg/cloudbroker/vins/search.go new file mode 100644 index 0000000..ffdf1f9 --- /dev/null +++ b/pkg/cloudbroker/vins/search.go @@ -0,0 +1,49 @@ +package vins + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for search VINSes +type SearchRequest struct { + // ID of the account to search for the ViNSes + // Required: false + AccountID uint64 `url:"accountId,omitempty"` + + // ID of the resource group to limit search to the specified RG level only + // Required: false + RGID uint64 `url:"rgId,omitempty"` + + // Name of the ViNS to search for + // Required: false + Name string `url:"name,omitempty"` + + // If False, then VINSes having one of the statuses are not listed for + // Required: false + ShowAll bool `url:"show_all,omitempty"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +// Search search VINSes +func (v VINS) Search(ctx context.Context, req SearchRequest) (ListVINS, error) { + url := "/cloudbroker/vins/search" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListVINS{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/pkg/cloudbroker/vins/vins.go b/pkg/cloudbroker/vins/vins.go new file mode 100644 index 0000000..feb0426 --- /dev/null +++ b/pkg/cloudbroker/vins/vins.go @@ -0,0 +1,18 @@ +// API Actor for managing VINS. This actor is a final API for endusers to manage VINS +package vins + +import ( + "github.com/rudecs/decort-sdk/interfaces" +) + +// Structure for creating request to VINS +type VINS struct { + client interfaces.Caller +} + +// Builder for VINS endpoints +func New(client interfaces.Caller) *VINS { + return &VINS{ + client: client, + } +} diff --git a/pkg/cloudbroker/vins/vnfdev_redeploy.go b/pkg/cloudbroker/vins/vnfdev_redeploy.go new file mode 100644 index 0000000..2ad51bb --- /dev/null +++ b/pkg/cloudbroker/vins/vnfdev_redeploy.go @@ -0,0 +1,49 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for redeploy VNF devices +type VNFDevRedeployRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq VNFDevRedeployRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: fiels VINSID must be set") + } + + return nil +} + +// VNFDevRedeploy redeploy VINS VNFDevs +func (v VINS) VNFDevRedeploy(ctx context.Context, req VNFDevRedeployRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/vnfdevRedeploy" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/vnfdev_reset.go b/pkg/cloudbroker/vins/vnfdev_reset.go new file mode 100644 index 0000000..4134607 --- /dev/null +++ b/pkg/cloudbroker/vins/vnfdev_reset.go @@ -0,0 +1,49 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for reset VNF device +type VNFDevResetRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq VNFDevResetRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: fiels VINSID must be set") + } + + return nil +} + +// VNFDevReset reset VINSes primary VNF device +func (v VINS) VNFDevReset(ctx context.Context, req VNFDevResetRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/vnfdevReset" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/vnfdev_restart.go b/pkg/cloudbroker/vins/vnfdev_restart.go new file mode 100644 index 0000000..0b1da26 --- /dev/null +++ b/pkg/cloudbroker/vins/vnfdev_restart.go @@ -0,0 +1,49 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for reboot VINSes primary VNF device +type VNFDevRestartRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Reason for action + // Required: fal + Reason string `url:"reason,omitempty"` +} + +func (vrq VNFDevRestartRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: fiels VINSID must be set") + } + + return nil +} + +// VNFDevRestart reboot VINSes primary VNF device +func (v VINS) VNFDevRestart(ctx context.Context, req VNFDevRestartRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/vnfdevRestart" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/vnfdev_start.go b/pkg/cloudbroker/vins/vnfdev_start.go new file mode 100644 index 0000000..21a4ae2 --- /dev/null +++ b/pkg/cloudbroker/vins/vnfdev_start.go @@ -0,0 +1,49 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for start VNF devices +type VNFDevStartRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Reason for action + // Required: false + Reason string `url:"reason,omitempty"` +} + +func (vrq VNFDevStartRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: fiels VINSID must be set") + } + + return nil +} + +// VNFDevStart starts VINSes primary VNF device +func (v VINS) VNFDevStart(ctx context.Context, req VNFDevStartRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/vnfdevStart" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudbroker/vins/vnfdev_stop.go b/pkg/cloudbroker/vins/vnfdev_stop.go new file mode 100644 index 0000000..a13b006 --- /dev/null +++ b/pkg/cloudbroker/vins/vnfdev_stop.go @@ -0,0 +1,49 @@ +package vins + +import ( + "context" + "errors" + "net/http" + "strconv" +) + +// Request struct for stop VNF devices +type VNFDevStopRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId"` + + // Reason for action + // Required: true + Reason string `url:"reason,omitempty"` +} + +func (vrq VNFDevStopRequest) validate() error { + if vrq.VINSID == 0 { + return errors.New("validation-error: fiels VINSID must be set") + } + + return nil +} + +// VNFDevStop stop VINSes primary VNF device +func (v VINS) VNFDevStop(ctx context.Context, req VNFDevStopRequest) (bool, error) { + err := req.validate() + if err != nil { + return false, err + } + + url := "/cloudbroker/vins/vnfdevStop" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +}