Skip to content
This repository has been archived by the owner on Dec 7, 2023. It is now read-only.

Commit

Permalink
Add the initial v1alpha1 API types for Ignite using k8s apimachinery
Browse files Browse the repository at this point in the history
  • Loading branch information
luxas committed Jul 2, 2019
1 parent 09d51ab commit ca1edc8
Show file tree
Hide file tree
Showing 7 changed files with 756 additions and 0 deletions.
57 changes: 57 additions & 0 deletions pkg/apis/ignite/scheme/scheme.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package scheme

import (
"io/ioutil"

"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"

"github.com/weaveworks/ignite/pkg/apis/ignite/v1alpha1"
)

var (
// Scheme is the runtime.Scheme to which all types are registered.
Scheme = runtime.NewScheme()

// Codecs provides access to encoding and decoding for the scheme.
Codecs = serializer.NewCodecFactory(Scheme)
)

func init() {
AddToScheme(Scheme)
}

// AddToScheme builds the scheme using all known versions of the api.
func AddToScheme(scheme *runtime.Scheme) {
utilruntime.Must(v1alpha1.AddToScheme(Scheme))
utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion))
}

// DecodeFileInto takes a file path and a target object to serialize the data into
func DecodeFileInto(filePath string, obj runtime.Object) error {
content, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}

return DecodeInto(content, obj)
}

// DecodeInto takes byte content and a target object to serialize the data into
func DecodeInto(content []byte, obj runtime.Object) error {
return runtime.DecodeInto(Codecs.UniversalDecoder(), content, obj)
}

// EncodeYAML encodes the specified object for a specific version to YAML bytes
func EncodeYAML(obj runtime.Object, groupVersion schema.GroupVersion) ([]byte, error) {
serializerInfo, _ := runtime.SerializerInfoForMediaType(Codecs.SupportedMediaTypes(), runtime.ContentTypeYAML)
return runtime.Encode(Codecs.EncoderForVersion(serializerInfo.Serializer, groupVersion), obj)
}

// EncodeYAML encodes the specified object for a specific version to pretty JSON bytes
func EncodeJSON(obj runtime.Object, groupVersion schema.GroupVersion) ([]byte, error) {
serializerInfo, _ := runtime.SerializerInfoForMediaType(Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON)
return runtime.Encode(Codecs.EncoderForVersion(serializerInfo.PrettySerializer, groupVersion), obj)
}
66 changes: 66 additions & 0 deletions pkg/apis/ignite/v1alpha1/defaults.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package v1alpha1

import (
ignitemeta "github.com/weaveworks/ignite/pkg/apis/meta/v1alpha1"
"github.com/weaveworks/ignite/pkg/constants"
"k8s.io/apimachinery/pkg/runtime"
)

func addDefaultingFuncs(scheme *runtime.Scheme) error {
return RegisterDefaults(scheme)
}

func SetDefaults_ImageSource(obj *ImageSource) {
obj.Type = ImageSourceTypeDocker
}

func SetDefaults_PoolSpec(obj *PoolSpec) {
if obj.AllocationSize == ignitemeta.EmptySize {
obj.AllocationSize = ignitemeta.NewSizeFromSectors(constants.POOL_ALLOCATION_SIZE_SECTORS)
}

if obj.DataSize == ignitemeta.EmptySize {
obj.AllocationSize = ignitemeta.NewSizeFromBytes(constants.POOL_DATA_SIZE_BYTES)
}

if obj.MetadataSize == ignitemeta.EmptySize {
obj.AllocationSize = calcMetadataDevSize(obj)
}

if len(obj.MetadataPath) == 0 {
obj.MetadataPath = constants.SNAPSHOTTER_METADATA_PATH
}

if len(obj.DataPath) == 0 {
obj.DataPath = constants.SNAPSHOTTER_DATA_PATH
}
}

func SetDefaults_VMSpec(obj *VMSpec) {
if obj.CPUs == 0 {
obj.CPUs = constants.VM_DEFAULT_CPUS
}

// TODO: These might be nil instead of ignitemeta.EmptySize
if obj.Memory == ignitemeta.EmptySize {
obj.Memory = ignitemeta.NewSizeFromBytes(constants.VM_DEFAULT_MEMORY)
}

if obj.Size == ignitemeta.EmptySize {
obj.Size = ignitemeta.NewSizeFromBytes(constants.VM_DEFAULT_SIZE)
}
}

func SetDefaults_VMStatus(obj *VMStatus) {
if obj.State == "" {
obj.State = VMStateCreated
}
}

func calcMetadataDevSize(obj *PoolSpec) ignitemeta.Size {
// The minimum size is 2 MB and the maximum size is 16 GB
minSize := ignitemeta.NewSizeFromBytes(2 * constants.MB)
maxSize := ignitemeta.NewSizeFromBytes(16 * constants.GB)

return ignitemeta.NewSizeFromBytes(48 * obj.DataSize.Bytes() / obj.AllocationSize.Bytes()).Min(maxSize).Max(minSize)
}
3 changes: 3 additions & 0 deletions pkg/apis/ignite/v1alpha1/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// +k8s:deepcopy-gen=package
// +k8s:defaulter-gen=TypeMeta
package v1alpha1
38 changes: 38 additions & 0 deletions pkg/apis/ignite/v1alpha1/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package v1alpha1

import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)

var (
// SchemeBuilder the schema builder
SchemeBuilder = runtime.NewSchemeBuilder(
addKnownTypes,
addDefaultingFuncs,
)

localSchemeBuilder = &SchemeBuilder
AddToScheme = localSchemeBuilder.AddToScheme
)

// GroupName is the group name use in this package
const GroupName = "ignite.weave.works"

// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{
Group: GroupName,
Version: "v1alpha1",
}

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&VM{},
&Kernel{},
&Pool{},
&Image{},
)

return nil
}
194 changes: 194 additions & 0 deletions pkg/apis/ignite/v1alpha1/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
package v1alpha1

import (
"net"

ignitemeta "github.com/weaveworks/ignite/pkg/apis/meta/v1alpha1"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Image represents a cached OCI image ready to be used with Ignite
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type Image struct {
metav1.TypeMeta `json:",inline"`
// ignitemeta.ObjectMeta is also embedded into the struct, and defines the human-readable name, and the machine-readable ID
// Name is available at the .metadata.name JSON path
// ID is available at the .metadata.uid JSON path (the Go type is k8s.io/apimachinery/pkg/types.UID, which is only a typed string)
ignitemeta.ObjectMeta `json:"metadata"`

Spec ImageSpec `json:"spec"`
Status ImageStatus `json:"status"`
}

// ImageSpec declares what the image contains
type ImageSpec struct {
Source ImageSource `json:"source"`
}

// ImageSourceType is an enum of different supported Image Source Types
type ImageSourceType string

const (
// ImageSourceTypeDocker defines that the image is imported from Docker
ImageSourceTypeDocker ImageSourceType = "Docker"
)

// ImageSource defines where the image was imported from
type ImageSource struct {
// Type defines how the image was imported
Type ImageSourceType `json:"type"`
// ID defines the source's ID (e.g. the Docker image ID)
ID string `json:"id"`
// Name defines the user-friendly name of the imported source
Name string `json:"name"`
// ignitemeta.Size defines the size of the source in bytes
Size ignitemeta.Size `json:"size"`
}

// ImageStatus defines the status of the image
type ImageStatus struct {
// LayerID points to the index of the device in the DM pool
LayerID ignitemeta.DMID `json:"layerID"`
}

// Pool defines device mapper pool database
// This file is managed by the snapshotter part of Ignite, and the file (existing as a singleton)
// is present at /var/lib/firecracker/snapshotter/pool.json
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type Pool struct {
metav1.TypeMeta `json:",inline"`
// Not needed (yet)
// ignitemeta.ObjectMeta `json:"metadata"`

Spec PoolSpec `json:"spec"`
Status PoolStatus `json:"status"`
}

// PoolSpec defines the Pool's specification
type PoolSpec struct {
// MetadataSize specifies the size of the pool's metadata
MetadataSize ignitemeta.Size `json:"metadataSize"`
// DataSize specifies the size of the pool's data
DataSize ignitemeta.Size `json:"dataSize"`
// AllocationSize specifies the smallest size that can be allocated at a time
AllocationSize ignitemeta.Size `json:"allocationSize"`
// MetadataPath points to the file where device mapper stores all metadata information
// Defaults to constants.SNAPSHOTTER_METADATA_PATH
MetadataPath string `json:"metadataPath"`
// DataPath points to the backing physical device or sparse file (to be loop mounted) for the pool
// Defaults to constants.SNAPSHOTTER_DATA_PATH
DataPath string `json:"dataPath"`
}

// PoolStatus defines the Pool's current status
type PoolStatus struct {
// The Devices array needs to contain pointers to accommodate "holes" in the mapping
// Where devices have been deleted, the pointer is nil
Devices []*PoolDevice `json:"devices"`
}

type PoolDeviceType string

const (
PoolDeviceTypeImage PoolDeviceType = "Image"
PoolDeviceTypeResize PoolDeviceType = "Resize"
PoolDeviceTypeKernel PoolDeviceType = "Kernel"
PoolDeviceTypeVM PoolDeviceType = "VM"
)

// PoolDevice defines one device in the pool
type PoolDevice struct {
Size ignitemeta.Size `json:"size"`
Parent ignitemeta.DMID `json:"parent"`
// Type specifies the type of the contents of the device
Type PoolDeviceType `json:"type"`
// MetadataPath points to the JSON/YAML file with metadata about this device
// This is most often of the format /var/lib/firecracker/{type}/{id}/metadata.json
MetadataPath string `json:"metadataPath"`
}

// Kernel is a serializable object that caches information about imported kernels
// This file is stored in /var/lib/firecracker/kernels/{oci-image-digest}/metadata.json
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type Kernel struct {
metav1.TypeMeta `json:",inline"`
// ignitemeta.ObjectMeta is also embedded into the struct, and defines the human-readable name, and the machine-readable ID
// Name is available at the .metadata.name JSON path
// ID is available at the .metadata.uid JSON path (the Go type is k8s.io/apimachinery/pkg/types.UID, which is only a typed string)
ignitemeta.ObjectMeta `json:"metadata"`

Spec KernelSpec `json:"spec"`
//Status KernelStatus `json:"status"`
}

// KernelSpec describes the properties of a kernel
type KernelSpec struct {
Version string `json:"version"`
Source ImageSource `json:"source"`
// Optional future feature, support per-kernel specific default command lines
// DefaultCmdLine string
}

// VM represents a virtual machine run by Firecracker
// These files are stored in /var/lib/firecracker/vm/{vm-id}/metadata.json
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type VM struct {
metav1.TypeMeta `json:",inline"`
// ignitemeta.ObjectMeta is also embedded into the struct, and defines the human-readable name, and the machine-readable ID
// Name is available at the .metadata.name JSON path
// ID is available at the .metadata.uid JSON path (the Go type is k8s.io/apimachinery/pkg/types.UID, which is only a typed string)
ignitemeta.ObjectMeta `json:"metadata"`

Spec VMSpec `json:"spec"`
Status VMStatus `json:"status"`
}

// VMSpec describes the configuration of a VM
type VMSpec struct {
CPUs uint64 `json:"cpus"`
Memory ignitemeta.Size `json:"memory"`
Size ignitemeta.Size `json:"size"`
Ports []PortMapping `json:"ports"`
// This will be done at either "ignite start" or "ignite create" time
// TODO: We might to revisit this later
CopyFiles []FileMapping `json:"copyFiles"`
// SSH specifies how the SSH setup should be done
// SSH appends to CopyFiles when active
// nil here means "don't do anything special"
// An empty struct means "generate a new SSH key and copy it in"
// Specifying a path means "use this public key"
SSH *SSH `json:"ssh"`
}

// PortMapping defines a port mapping between the VM and the host
type PortMapping struct {
HostPort uint64 `json:"hostPort"`
VMPort uint64 `json:"vmPort"`
}

// FileMapping defines mappings between files on the host and VM
type FileMapping struct {
HostPath string `json:"hostPath"`
VMPath string `json:"vmPath"`
}

// SSH specifies different ways to connect via SSH to the VM
type SSH struct {
PublicKey string `json:"publicKey"`
}

// VMState defines different states a VM can be in
type VMState string

const (
VMStateCreated VMState = "Created"
VMStateRunning VMState = "Running"
VMStateStopped VMState = "Stopped"
)

// VMStatus defines the status of a VM
type VMStatus struct {
State VMState `json:"state"`
IPAddresses []net.IP `json:"ipAddresses"`
}
Loading

0 comments on commit ca1edc8

Please sign in to comment.