Skip to content

Commit

Permalink
Merge pull request #36 from bjwswang/llms
Browse files Browse the repository at this point in the history
feat: define CRD LLM and update helm charts
  • Loading branch information
bjwswang authored Aug 16, 2023
2 parents b3f654b + c694d5f commit 0427c85
Show file tree
Hide file tree
Showing 13 changed files with 637 additions and 36 deletions.
181 changes: 181 additions & 0 deletions api/v1alpha1/condition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
Copyright 2023 KubeAGI.
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 v1alpha1

import (
"sort"

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

// A ConditionType represents a condition a resource could be in.
type ConditionType string

// Some common Condition types.
const (
// TypeReady resources are believed to be ready to handle work.
TypeReady ConditionType = "Ready"
// TypeUnknown resources are unknown to the system
TypeUnknown ConditionType = "Unknown"
)

// A ConditionReason represents the reason a resource is in a condition.
// Should be only one word
type ConditionReason string

// Some common Condition resons.
const (
ReasonAvailable ConditionReason = "Available"
ReasonUnavailable ConditionReason = "Unavailable"
ReasonCreating ConditionReason = "Creating"
ReasonDeleting ConditionReason = "Deleting"
ReasonReconcileSuccess ConditionReason = "ReconcileSuccess"
ReasonReconcileError ConditionReason = "ReconcileError"
ReasonReconcilePaused ConditionReason = "ReconcilePaused"
)

// A Condition that may apply to a resource.
type Condition struct {
// Type of this condition. At most one of each condition type may apply to
// a resource at any point in time.
Type ConditionType `json:"type"`

// Status of this condition; is it currently True, False, or Unknown
Status corev1.ConditionStatus `json:"status"`

// LastTransitionTime is the last time this condition transitioned from one
// status to another.
LastTransitionTime metav1.Time `json:"lastTransitionTime"`

// LastSuccessfulTime is repository Last Successful Update Time
LastSuccessfulTime metav1.Time `json:"lastSuccessfulTime,omitempty"`

// A Reason for this condition's last transition from one status to another.
Reason ConditionReason `json:"reason"`

// A Message containing details about this condition's last transition from
// one status to another, if any.
// +optional
Message string `json:"message,omitempty"`
}

// Equal returns true if the condition is identical to the supplied condition
func (c Condition) Equal(other Condition) bool {
return c.Type == other.Type &&
c.Status == other.Status &&
c.Reason == other.Reason &&
c.Message == other.Message &&
c.LastSuccessfulTime.Equal(&other.LastSuccessfulTime) &&
c.LastTransitionTime.Equal(&other.LastTransitionTime)
}

// WithMessage returns a condition by adding the provided message to existing
// condition.
func (c Condition) WithMessage(msg string) Condition {
c.Message = msg
return c
}

// NOTE: Conditions are implemented as a slice rather than a map to comply
// with Kubernetes API conventions. Ideally we'd comply by using a map that
// marshaled to a JSON array, but doing so confuses the CRD schema generator.
// https://github.com/kubernetes/community/blob/9bf8cd/contributors/devel/sig-architecture/api-conventions.md#lists-of-named-subobjects-preferred-over-maps

// NOTE: Do not manipulate Conditions directly. Use the Set method.

// A ConditionedStatus reflects the observed status of a resource. Only
// one condition of each type may exist.
type ConditionedStatus struct {
// Conditions of the resource.
// +optional
Conditions []Condition `json:"conditions,omitempty"`
}

// NewConditionedStatus returns a stat with the supplied conditions set.
func NewConditionedStatus(c ...Condition) *ConditionedStatus {
s := &ConditionedStatus{}
s.SetConditions(c...)
return s
}

// GetCondition returns the condition for the given ConditionType if exists,
// otherwise returns nil
func (s *ConditionedStatus) GetCondition(ct ConditionType) Condition {
for _, c := range s.Conditions {
if c.Type == ct {
return c
}
}

return Condition{Type: ct, Status: corev1.ConditionUnknown}
}

// SetConditions sets the supplied conditions, replacing any existing conditions
// of the same type. This is a no-op if all supplied conditions are identical,
// ignoring the last transition time, to those already set.
func (s *ConditionedStatus) SetConditions(c ...Condition) {
for _, new := range c {
exists := false
for i, existing := range s.Conditions {
if existing.Type != new.Type {
continue
}

if existing.Equal(new) {
exists = true
continue
}

s.Conditions[i] = new
exists = true
}
if !exists {
s.Conditions = append(s.Conditions, new)
}
}
}

// Equal returns true if the status is identical to the supplied status,
// ignoring the LastTransitionTimes and order of statuses.
func (s *ConditionedStatus) Equal(other *ConditionedStatus) bool {
if s == nil || other == nil {
return s == nil && other == nil
}

if len(other.Conditions) != len(s.Conditions) {
return false
}

sc := make([]Condition, len(s.Conditions))
copy(sc, s.Conditions)

oc := make([]Condition, len(other.Conditions))
copy(oc, other.Conditions)

// We should not have more than one condition of each type.
sort.Slice(sc, func(i, j int) bool { return sc[i].Type < sc[j].Type })
sort.Slice(oc, func(i, j int) bool { return oc[i].Type < oc[j].Type })

for i := range sc {
if !sc[i].Equal(oc[i]) {
return false
}
}

return true
}
41 changes: 41 additions & 0 deletions api/v1alpha1/llm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
Copyright 2023 KubeAGI.
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 v1alpha1

import (
"errors"

corev1 "k8s.io/api/core/v1"
)

var (
ErrMissingAPIKey = errors.New("missing apikey in auth info")
)

type LLMType string

const (
OpenAI LLMType = "openai"
)

func (o *AuthInfo) FromSecret(secret corev1.Secret) error {
o.APIKey = string(secret.Data["apiKey"])
if o.APIKey == "" {
return ErrMissingAPIKey
}
return nil
}
22 changes: 13 additions & 9 deletions api/v1alpha1/llm_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,26 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

// LLMSpec defines the desired state of LLM
type LLMSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
DisplayName string `json:"displayName,omitempty"`
// Type defines the type of llm
Type LLMType `json:"type"`
// URL keeps the URL of the llm service(Must required)
URL string `json:"url"`
// Auth keeps the authentication credentials when access llm
// keeps in k8s secret
Auth string `json:"auth,omitempty"`
}

// Foo is an example field of LLM. Edit llm_types.go to remove/update
Foo string `json:"foo,omitempty"`
type AuthInfo struct {
APIKey string `json:"apiKey,omitempty"`
}

// LLMStatus defines the observed state of LLM
type LLMStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
// ConditionedStatus is the current status
ConditionedStatus `json:",inline"`
}

//+kubebuilder:object:root=true
Expand Down
57 changes: 56 additions & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 9 additions & 19 deletions charts/arcadia/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,24 +1,14 @@
apiVersion: v2
name: arcadia
description: A Helm chart(KubeBB Component) for KubeAGI Arcadia

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
version: 0.1.1
appVersion: "0.0.0"
keywords:
- kubeagi
- NativeAI
sources:
- https://github.com/kubeagi/arcadia
maintainers:
- name: bjwswang
url: https://github.com/bjwswang
Loading

0 comments on commit 0427c85

Please sign in to comment.