初始提交:OCI 面板后端(含 GenAI 网关一期)
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
package oci
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/oracle/oci-go-sdk/v65/core"
|
||||
)
|
||||
|
||||
func TestShellSingleQuote(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
in string
|
||||
want string
|
||||
}{
|
||||
{name: "普通", in: "Passw0rd", want: "'Passw0rd'"},
|
||||
{name: "含单引号", in: "a'b", want: `'a'\''b'`},
|
||||
{name: "含空格特殊符", in: "p @ss!", want: "'p @ss!'"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := shellSingleQuote(tt.in); got != tt.want {
|
||||
t.Errorf("shellSingleQuote(%q) = %q, want %q", tt.in, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRootPasswordUserData(t *testing.T) {
|
||||
encoded := rootPasswordUserData("Secret123")
|
||||
raw, err := base64.StdEncoding.DecodeString(encoded)
|
||||
if err != nil {
|
||||
t.Fatalf("result is not base64: %v", err)
|
||||
}
|
||||
script := string(raw)
|
||||
for _, want := range []string{
|
||||
"#!/bin/bash",
|
||||
"echo root:'Secret123' | chpasswd",
|
||||
"PermitRootLogin yes",
|
||||
"PasswordAuthentication yes",
|
||||
"systemctl restart sshd",
|
||||
} {
|
||||
if !strings.Contains(script, want) {
|
||||
t.Errorf("script missing %q\n---\n%s", want, script)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildInstanceMetadataRootPasswordOverridesUserData(t *testing.T) {
|
||||
md := buildInstanceMetadata(CreateInstanceInput{
|
||||
RootPassword: "pw",
|
||||
UserData: "ZXhwbGljaXQ=", // "explicit"
|
||||
})
|
||||
decoded, _ := base64.StdEncoding.DecodeString(md["user_data"])
|
||||
if !strings.Contains(string(decoded), "chpasswd") {
|
||||
t.Errorf("user_data = %q, want root password script (not explicit userData)", md["user_data"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildInstanceSourceVpusPerGB(t *testing.T) {
|
||||
src := buildInstanceSource(CreateInstanceInput{ImageID: "img", BootVolumeSizeGBs: 100, BootVolumeVpusPerGB: 20})
|
||||
img, ok := src.(core.InstanceSourceViaImageDetails)
|
||||
if !ok {
|
||||
t.Fatalf("source type = %T, want image", src)
|
||||
}
|
||||
if img.BootVolumeVpusPerGB == nil || *img.BootVolumeVpusPerGB != 20 {
|
||||
t.Errorf("BootVolumeVpusPerGB = %v, want 20", img.BootVolumeVpusPerGB)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildInstanceSource(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
in CreateInstanceInput
|
||||
wantType string
|
||||
}{
|
||||
{
|
||||
name: "从镜像启动",
|
||||
in: CreateInstanceInput{ImageID: "ocid1.image..a", BootVolumeSizeGBs: 100},
|
||||
wantType: "image",
|
||||
},
|
||||
{
|
||||
name: "从引导卷启动",
|
||||
in: CreateInstanceInput{BootVolumeID: "ocid1.bootvolume..b"},
|
||||
wantType: "bootVolume",
|
||||
},
|
||||
{
|
||||
name: "引导卷优先于镜像",
|
||||
in: CreateInstanceInput{ImageID: "ocid1.image..a", BootVolumeID: "ocid1.bootvolume..b"},
|
||||
wantType: "bootVolume",
|
||||
},
|
||||
{
|
||||
name: "两者皆无返回 nil",
|
||||
in: CreateInstanceInput{},
|
||||
wantType: "nil",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
src := buildInstanceSource(tt.in)
|
||||
switch tt.wantType {
|
||||
case "image":
|
||||
img, ok := src.(core.InstanceSourceViaImageDetails)
|
||||
if !ok {
|
||||
t.Fatalf("source type = %T, want InstanceSourceViaImageDetails", src)
|
||||
}
|
||||
if got, want := *img.BootVolumeSizeInGBs, tt.in.BootVolumeSizeGBs; got != want {
|
||||
t.Errorf("BootVolumeSizeInGBs = %d, want %d", got, want)
|
||||
}
|
||||
case "bootVolume":
|
||||
if _, ok := src.(core.InstanceSourceViaBootVolumeDetails); !ok {
|
||||
t.Fatalf("source type = %T, want InstanceSourceViaBootVolumeDetails", src)
|
||||
}
|
||||
case "nil":
|
||||
if src != nil {
|
||||
t.Fatalf("source = %v, want nil", src)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildLaunchDetails(t *testing.T) {
|
||||
in := CreateInstanceInput{
|
||||
AvailabilityDomain: "AD-1",
|
||||
DisplayName: "vm1",
|
||||
Shape: "VM.Standard.A1.Flex",
|
||||
Ocpus: 2,
|
||||
MemoryInGBs: 12,
|
||||
ImageID: "ocid1.image..a",
|
||||
SubnetID: "ocid1.subnet..s",
|
||||
AssignPublicIP: true,
|
||||
AssignIpv6: true,
|
||||
SSHPublicKey: "ssh-ed25519 AAA",
|
||||
}
|
||||
details, err := buildLaunchDetails("ocid1.tenancy..t", in)
|
||||
if err != nil {
|
||||
t.Fatalf("buildLaunchDetails: %v", err)
|
||||
}
|
||||
if got, want := *details.ShapeConfig.Ocpus, float32(2); got != want {
|
||||
t.Errorf("Ocpus = %v, want %v", got, want)
|
||||
}
|
||||
if got, want := *details.ShapeConfig.MemoryInGBs, float32(12); got != want {
|
||||
t.Errorf("MemoryInGBs = %v, want %v", got, want)
|
||||
}
|
||||
if got, want := *details.CreateVnicDetails.SubnetId, in.SubnetID; got != want {
|
||||
t.Errorf("SubnetId = %v, want %v", got, want)
|
||||
}
|
||||
if details.CreateVnicDetails.AssignIpv6Ip == nil || !*details.CreateVnicDetails.AssignIpv6Ip {
|
||||
t.Error("AssignIpv6Ip not set, want true")
|
||||
}
|
||||
if got, want := details.Metadata["ssh_authorized_keys"], in.SSHPublicKey; got != want {
|
||||
t.Errorf("ssh_authorized_keys = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildLaunchDetailsRequiresSource(t *testing.T) {
|
||||
_, err := buildLaunchDetails("ocid1.tenancy..t", CreateInstanceInput{
|
||||
AvailabilityDomain: "AD-1", DisplayName: "vm1", Shape: "shape", SubnetID: "sub",
|
||||
})
|
||||
if err == nil {
|
||||
t.Error("buildLaunchDetails without source: got nil error, want failure")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildLaunchDetailsNoShapeConfig(t *testing.T) {
|
||||
details, err := buildLaunchDetails("t", CreateInstanceInput{
|
||||
AvailabilityDomain: "AD-1", DisplayName: "vm1", Shape: "VM.Standard.E2.1.Micro",
|
||||
ImageID: "img", SubnetID: "sub",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("buildLaunchDetails: %v", err)
|
||||
}
|
||||
if details.ShapeConfig != nil {
|
||||
t.Errorf("ShapeConfig = %+v, want nil for fixed shape", details.ShapeConfig)
|
||||
}
|
||||
if details.Metadata != nil {
|
||||
t.Errorf("Metadata = %v, want nil when no key and user data", details.Metadata)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user