mirror of
https://github.com/hanzoai/vm.git
synced 2026-10-01 00:47:56 +00:00
- Rename Go module from github.com/casvisor/casvisor to github.com/hanzoai/visor - Update all copyright headers from casbin to Hanzo Industries Inc - Remove all hardcoded passwords and credentials from config files - All credentials now sourced from environment variables / Hanzo KMS - Switch default database from MySQL to PostgreSQL (matching production) - Rename binary output from server/casvisor to visor - Update Dockerfile, build.sh, docker-compose.yml, docker-entrypoint.sh - Replace casdoor* config key references with iam* equivalents - Update CI to use PostgreSQL service and mark CI-only test password - Add visor and casvisor binaries to .gitignore - Add envFrom secretRef for visor-env in K8s deployment - Add ExternalSecret template for Hanzo KMS credential provisioning Co-authored-by: Hanzo Dev <[email protected]>
191 lines
5.1 KiB
Go
191 lines
5.1 KiB
Go
// Copyright 2023 Hanzo Industries Inc. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package service
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/aws/aws-sdk-go-v2/aws"
|
|
"github.com/aws/aws-sdk-go-v2/config"
|
|
"github.com/aws/aws-sdk-go-v2/service/ec2"
|
|
ec2Types "github.com/aws/aws-sdk-go-v2/service/ec2/types"
|
|
)
|
|
|
|
type MachineAwsClient struct {
|
|
Client *ec2.Client
|
|
region string
|
|
}
|
|
|
|
func newMachineAwsClient(accessKeyId string, accessKeySecret string, region string) (MachineAwsClient, error) {
|
|
cfg, err := config.LoadDefaultConfig(context.TODO(),
|
|
config.WithRegion(region),
|
|
config.WithCredentialsProvider(aws.CredentialsProviderFunc(func(ctx context.Context) (aws.Credentials, error) {
|
|
return aws.Credentials{
|
|
AccessKeyID: accessKeyId,
|
|
SecretAccessKey: accessKeySecret,
|
|
}, nil
|
|
})),
|
|
)
|
|
if err != nil {
|
|
return MachineAwsClient{}, err
|
|
}
|
|
|
|
client := ec2.NewFromConfig(cfg)
|
|
return MachineAwsClient{Client: client, region: region}, nil
|
|
}
|
|
|
|
func getMachineFromAwsInstance(instance ec2Types.Instance) *Machine {
|
|
machine := &Machine{
|
|
Name: *instance.InstanceId,
|
|
Id: *instance.InstanceId,
|
|
Region: *instance.Placement.AvailabilityZone,
|
|
DisplayName: *instance.InstanceId,
|
|
}
|
|
|
|
if instance.InstanceType != "" {
|
|
machine.Size = string(instance.InstanceType)
|
|
}
|
|
|
|
if len(instance.Tags) > 0 {
|
|
for _, tag := range instance.Tags {
|
|
machine.Tag += fmt.Sprintf("%s=%s,", *tag.Key, *tag.Value)
|
|
}
|
|
}
|
|
|
|
machine.State = string(instance.State.Name)
|
|
|
|
return machine
|
|
}
|
|
|
|
func (client MachineAwsClient) GetMachines() ([]*Machine, error) {
|
|
input := &ec2.DescribeInstancesInput{}
|
|
output, err := client.Client.DescribeInstances(context.TODO(), input)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
machines := []*Machine{}
|
|
for _, reservation := range output.Reservations {
|
|
for _, instance := range reservation.Instances {
|
|
machine := getMachineFromAwsInstance(instance)
|
|
machines = append(machines, machine)
|
|
}
|
|
}
|
|
|
|
return machines, nil
|
|
}
|
|
|
|
func (client MachineAwsClient) GetMachine(name string) (*Machine, error) {
|
|
input := &ec2.DescribeInstancesInput{
|
|
InstanceIds: []string{name},
|
|
}
|
|
|
|
output, err := client.Client.DescribeInstances(context.TODO(), input)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(output.Reservations) == 0 || len(output.Reservations[0].Instances) == 0 {
|
|
return nil, fmt.Errorf("Instance not found: %s", name)
|
|
}
|
|
|
|
instance := output.Reservations[0].Instances[0]
|
|
return getMachineFromAwsInstance(instance), nil
|
|
}
|
|
|
|
func (client MachineAwsClient) UpdateMachineState(name string, state string) (bool, string, error) {
|
|
switch state {
|
|
case "Running":
|
|
input := &ec2.StartInstancesInput{
|
|
InstanceIds: []string{name},
|
|
}
|
|
_, err := client.Client.StartInstances(context.TODO(), input)
|
|
if err != nil {
|
|
return false, "", err
|
|
}
|
|
case "Stopped":
|
|
input := &ec2.StopInstancesInput{
|
|
InstanceIds: []string{name},
|
|
}
|
|
_, err := client.Client.StopInstances(context.TODO(), input)
|
|
if err != nil {
|
|
return false, "", err
|
|
}
|
|
default:
|
|
return false, fmt.Sprintf("Unsupported state: %s", state), nil
|
|
}
|
|
|
|
return true, fmt.Sprintf("Instance: [%s]'s state has been successfully updated to: [%s]", name, state), nil
|
|
}
|
|
|
|
func (client MachineAwsClient) CreateMachine(spec *CreateMachineSpec) (*Machine, error) {
|
|
if spec.ImageID == "" {
|
|
return nil, fmt.Errorf("imageId is required for AWS instance creation")
|
|
}
|
|
|
|
instanceType := ec2Types.InstanceType(spec.InstanceType)
|
|
if spec.InstanceType == "" {
|
|
instanceType = ec2Types.InstanceTypeT3Medium
|
|
}
|
|
|
|
// Build tags
|
|
var tags []ec2Types.Tag
|
|
tags = append(tags, ec2Types.Tag{
|
|
Key: aws.String("Name"),
|
|
Value: aws.String(spec.DisplayName),
|
|
})
|
|
if spec.OS != "" {
|
|
tags = append(tags, ec2Types.Tag{
|
|
Key: aws.String("OS"),
|
|
Value: aws.String(spec.OS),
|
|
})
|
|
}
|
|
tags = append(tags, ec2Types.Tag{
|
|
Key: aws.String("ManagedBy"),
|
|
Value: aws.String("hanzo-visor"),
|
|
})
|
|
for k, v := range spec.Tags {
|
|
tags = append(tags, ec2Types.Tag{
|
|
Key: aws.String(k),
|
|
Value: aws.String(v),
|
|
})
|
|
}
|
|
|
|
input := &ec2.RunInstancesInput{
|
|
ImageId: aws.String(spec.ImageID),
|
|
InstanceType: instanceType,
|
|
MinCount: aws.Int32(1),
|
|
MaxCount: aws.Int32(1),
|
|
TagSpecifications: []ec2Types.TagSpecification{
|
|
{
|
|
ResourceType: ec2Types.ResourceTypeInstance,
|
|
Tags: tags,
|
|
},
|
|
},
|
|
}
|
|
|
|
output, err := client.Client.RunInstances(context.TODO(), input)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to launch EC2 instance: %w", err)
|
|
}
|
|
|
|
if len(output.Instances) == 0 {
|
|
return nil, fmt.Errorf("RunInstances returned no instances")
|
|
}
|
|
|
|
return getMachineFromAwsInstance(output.Instances[0]), nil
|
|
}
|