Skip to content

feat: op event publish;add opid #241

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/app.bytetrade.io/v1alpha1/application_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ type Entrance struct {
Title string `yaml:"title" json:"title,omitempty"`
AuthLevel string `yaml:"authLevel,omitempty" json:"authLevel,omitempty"`
Invisible bool `yaml:"invisible,omitempty" json:"invisible,omitempty"`
URL string `yaml:"url,omitempty" json:"url,omitempty"`

// openMethod has three choices default, iframe, window
// Optional. if invisible=true.
Expand Down
2 changes: 2 additions & 0 deletions api/app.bytetrade.io/v1alpha1/appmanager_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type ApplicationManagerStatus struct {

OpType OpType `json:"opType"`
OpGeneration int64 `json:"opGeneration"`
OpID string `json:"opId,omitempty"`
State ApplicationManagerState `json:"state,omitempty"`
OpRecords []OpRecord `json:"opRecords,omitempty"`
Message string `json:"message,omitempty"`
Expand All @@ -56,6 +57,7 @@ type ApplicationManagerSpec struct {
// OpRecord contains details of an operation.
type OpRecord struct {
OpType OpType `json:"opType"`
OpID string `json:"opId,omitempty"`
Message string `json:"message"`
Version string `json:"version"`
Source string `json:"source"`
Expand Down
4 changes: 4 additions & 0 deletions config/crd/bases/app.bytetrade.io_applicationmanagers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,16 @@ spec:
opGeneration:
format: int64
type: integer
opId:
type: string
opRecords:
items:
description: OpRecord contains details of an operation.
properties:
message:
type: string
opId:
type: string
opType:
description: OpType represents the type of operation being performed.
type: string
Expand Down
2 changes: 2 additions & 0 deletions config/crd/bases/app.bytetrade.io_applications.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ spec:
title:
description: Optional. if invisible=true.
type: string
url:
type: string
windowPushState:
type: boolean
required:
Expand Down
30 changes: 19 additions & 11 deletions config/crd/bases/app.bytetrade.io_imagemanagers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.9.2
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: imagemanagers.app.bytetrade.io
spec:
group: app.bytetrade.io
Expand Down Expand Up @@ -38,14 +37,19 @@ spec:
description: ImageManager is the Schema for the image managers API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
Expand Down Expand Up @@ -91,12 +95,16 @@ spec:
type: string
type: object
type: object
description: 'INSERT ADDITIONAL STATUS FIELD - define observed state
of cluster Important: Run "make" to regenerate code after modifying
this file'
description: |-
INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
Important: Run "make" to regenerate code after modifying this file
type: object
message:
type: string
nodeDownloadStatus:
additionalProperties:
type: string
type: object
state:
type: string
statusTime:
Expand Down
2 changes: 1 addition & 1 deletion controllers/application_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ func (r *ApplicationReconciler) updateApplication(ctx context.Context, req ctrl.
}

owner := deployment.GetLabels()[constants.ApplicationOwnerLabel]
klog.Infof("in updateApplication ....")
klog.Infof("in updateApplication ....appname: %v", app.Spec.Name)
icons := getAppIcon(deployment)
var icon string

Expand Down
10 changes: 10 additions & 0 deletions controllers/entrancestatus_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"

"bytetrade.io/web3os/app-service/api/app.bytetrade.io/v1alpha1"
"bytetrade.io/web3os/app-service/pkg/utils"

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -218,6 +219,7 @@ func (r *EntranceStatusManagerController) updateEntranceStatus(pod *corev1.Pod)
appCopy.Status.EntranceStatuses[i].StatusTime = &now
}
}

patchApp := client.MergeFrom(&selectedApp)
err = r.Status().Patch(context.TODO(), appCopy, patchApp)
klog.Infof("updateEntrances ...:name: %v", appCopy.Name)
Expand All @@ -226,6 +228,14 @@ func (r *EntranceStatusManagerController) updateEntranceStatus(pod *corev1.Pod)
klog.Errorf("failed to patch err=%v", err)
return err
}
var am v1alpha1.ApplicationManager
err = r.Get(context.TODO(), types.NamespacedName{Name: selectedApp.Name}, &am)
if err != nil {
klog.Errorf("failed to get am name=%s, err=%v", selectedApp.Name, err)
return err
}

utils.PublishAsync(appCopy.Spec.Owner, appCopy.Spec.Name, "", "", am.Status.State.String(), "", appCopy.Status.EntranceStatuses)
}
return nil
}
Expand Down
12 changes: 12 additions & 0 deletions controllers/eviction_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,18 @@ func (r *EvictionManagerController) Reconcile(ctx context.Context, req ctrl.Requ
if podNamespace == "" || ignoredNs.Has(podNamespace) {
return ctrl.Result{}, nil
}
//for _, v := range pod.Status.ContainerStatuses {
// if v.State.Terminated != nil {
// if v.State.Terminated.Reason == "Unknown" || v.State.Terminated.Reason == "ContainerStatusUnknown" {
// now := metav1.Now()
// err = r.Delete(ctx, &pod)
// if err != nil && !apierrors.IsNotFound(err) {
// return ctrl.Result{}, err
// }
// return ctrl.Result{}, nil
// }
// }
//}

if pod.Status.Reason != "Evicted" {
return ctrl.Result{}, nil
Expand Down
65 changes: 61 additions & 4 deletions controllers/image_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package controllers
import (
"context"
"errors"
"os"
"sync"

appv1alpha1 "bytetrade.io/web3os/app-service/api/app.bytetrade.io/v1alpha1"
Expand All @@ -25,6 +26,12 @@ import (
"sigs.k8s.io/controller-runtime/pkg/source"
)

var thisNode string

func init() {
thisNode = os.Getenv("NODE_NAME")
}

// ImageManagerController represents a controller for managing the lifecycle of applicationmanager.
type ImageManagerController struct {
client.Client
Expand Down Expand Up @@ -124,7 +131,7 @@ func (r *ImageManagerController) reconcile(ctx context.Context, instance *appv1a
}
imageManager[instance.Name] = cancel
if cur.Status.State != appv1alpha1.Downloading.String() {
err = r.updateStatus(ctx, &cur, appv1alpha1.Downloading.String(), "downloading")
err = r.updateStatus(ctx, &cur, appv1alpha1.Downloading.String(), "start downloading")
if err != nil {
klog.Infof("Failed to update imagemanager status name=%v, err=%v", cur.Name, err)
return err
Expand Down Expand Up @@ -156,10 +163,11 @@ func (r *ImageManagerController) reconcile(ctx context.Context, instance *appv1a

func (r *ImageManagerController) preEnqueueCheckForCreate(obj client.Object) bool {
im, _ := obj.(*appv1alpha1.ImageManager)
klog.Infof("enqueue check: %v", im.Status.State)
if im.Status.State == "failed" || im.Status.State == appv1alpha1.DownloadingCanceled.String() || im.Status.State == "completed" {
if im.Status.State == "failed" || im.Status.State == appv1alpha1.DownloadingCanceled.String() ||
im.Status.State == "completed" {
return false
}
klog.Infof("enqueue check: %v", im.Status.State)
return true
}

Expand Down Expand Up @@ -214,11 +222,60 @@ func (r *ImageManagerController) updateStatus(ctx context.Context, im *appv1alph

now := metav1.Now()
imCopy := im.DeepCopy()
imCopy.Status.State = state
if state != "completed" {
imCopy.Status.State = state
}
imCopy.Status.Message = message
imCopy.Status.StatusTime = &now
imCopy.Status.UpdateTime = &now

//if imCopy.Status.NodeDownloadStatus == nil {
// imCopy.Status.NodeDownloadStatus = make(map[string]string)
//}
//imCopy.Status.NodeDownloadStatus[thisNode] = state
if state == "completed" {
if _, ok := imCopy.Status.Conditions[thisNode]; !ok {
if imCopy.Status.Conditions == nil {
imCopy.Status.Conditions = make(map[string]map[string]map[string]string)
}
if imCopy.Status.Conditions[thisNode] == nil {
imCopy.Status.Conditions[thisNode] = make(map[string]map[string]string)
}
for _, ref := range imCopy.Spec.Refs {

imCopy.Status.Conditions[thisNode][ref.Name] = map[string]string{
"offset": "56782302",
"total": "56782302",
}
}
}

checkAllCompleted := func() bool {
for _, node := range imCopy.Spec.Nodes {
conditionsNode, ok := imCopy.Status.Conditions[node]
if !ok {
return false
}
for _, ref := range imCopy.Spec.Refs {
if _, ok := conditionsNode[ref.Name]["offset"]; !ok {
return false
}
if _, ok := conditionsNode[ref.Name]["total"]; !ok {
return false
}
if conditionsNode[ref.Name]["offset"] != conditionsNode[ref.Name]["total"] {
return false
}
}
}
return true
}
if checkAllCompleted() {
imCopy.Status.State = state
}

}

err = r.Status().Patch(ctx, imCopy, client.MergeFrom(im))
if err != nil {
return err
Expand Down
17 changes: 10 additions & 7 deletions controllers/image_info_controller.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
package controllers

import (
"bytetrade.io/web3os/app-service/pkg/images"
"bytetrade.io/web3os/app-service/pkg/utils"
"context"
"errors"
"fmt"
"github.com/containerd/containerd"
"github.com/containerd/containerd/errdefs"
"github.com/containers/image/v5/image"

"os"
"time"

appv1alpha1 "bytetrade.io/web3os/app-service/api/app.bytetrade.io/v1alpha1"
"bytetrade.io/web3os/app-service/pkg/images"
"bytetrade.io/web3os/app-service/pkg/utils"
imagetypes "github.com/containers/image/v5/types"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/util/retry"

"github.com/containerd/containerd"
"github.com/containerd/containerd/errdefs"
refdocker "github.com/containerd/containerd/reference/docker"

"github.com/containers/image/v5/image"
"github.com/containers/image/v5/transports/alltransports"
"k8s.io/klog/v2"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -278,7 +278,8 @@ func (r *AppImageInfoController) GetImageInfo(ctx context.Context, refs []string

manifest, err := r.GetManifest(ctx, replacedRef)
if err != nil {
return imageInfos, nil
klog.Infof("get image %s manifest failed %v", name.String(), err)
return imageInfos, err
}

imageInfo := appv1alpha1.ImageInfo{
Expand All @@ -299,6 +300,7 @@ func (r *AppImageInfoController) GetImageInfo(ctx context.Context, refs []string
_, err = r.imageClient.ContentStore().Info(ctx, layer.Digest)
if err == nil {
imageLayer.Offset = layer.Size
imageLayers = append(imageLayers, imageLayer)
// go next layer
continue
}
Expand All @@ -312,6 +314,7 @@ func (r *AppImageInfoController) GetImageInfo(ctx context.Context, refs []string
s := "layer-" + layer.Digest.String()
if s == status.Ref {
imageLayer.Offset = status.Offset
break
}
}
} else {
Expand Down
13 changes: 8 additions & 5 deletions controllers/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

appv1alpha1 "bytetrade.io/web3os/app-service/api/app.bytetrade.io/v1alpha1"
"bytetrade.io/web3os/app-service/pkg/appstate"

corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -58,21 +59,21 @@ func LoadStatefulApp(ctx context.Context, appmgr *ApplicationManagerController,
retApp, serr := func() (appstate.StatefulApp, appstate.StateError) {
switch am.Status.State {
case appv1alpha1.Pending:
return appstate.NewPendingApp(ctx, appmgr, &am, time.Hour)
return appstate.NewPendingApp(ctx, appmgr, &am, 24*time.Hour)
case appv1alpha1.Downloading:
return appstate.NewDownloadingApp(appmgr, &am, 2*time.Hour)
return appstate.NewDownloadingApp(appmgr, &am, 24*time.Hour)
case appv1alpha1.Installing:
return appstate.NewInstallingApp(appmgr, &am, 30*time.Minute)
case appv1alpha1.Initializing:
return appstate.NewInitializingApp(appmgr, &am, 30*time.Minute)
return appstate.NewInitializingApp(appmgr, &am, 60*time.Minute)
case appv1alpha1.Running:
return appstate.NewRunningApp(ctx, appmgr, &am)
case appv1alpha1.Stopping:
return appstate.NewSuspendingApp(appmgr, &am, 30*time.Minute)
case appv1alpha1.Upgrading:
return appstate.NewUpgradingApp(appmgr, &am, 30*time.Minute)
case appv1alpha1.Resuming:
return appstate.NewResumingApp(appmgr, &am, 30*time.Minute)
return appstate.NewResumingApp(appmgr, &am, 60*time.Minute)
case appv1alpha1.PendingCanceling:
return appstate.NewPendingCancelingApp(appmgr, &am)
case appv1alpha1.DownloadingCanceling:
Expand All @@ -96,12 +97,14 @@ func LoadStatefulApp(ctx context.Context, appmgr *ApplicationManagerController,
case appv1alpha1.ResumeFailed:
return appstate.NewResumeFailedApp(appmgr, &am)

case appv1alpha1.DownloadFailed, appv1alpha1.InstallFailed,
case appv1alpha1.DownloadFailed,
appv1alpha1.PendingCanceled, appv1alpha1.DownloadingCanceled,
appv1alpha1.InstallingCanceled, appv1alpha1.InitializingCanceled,
appv1alpha1.UpgradingCanceled, appv1alpha1.ResumingCanceled,
appv1alpha1.Stopped:
return appstate.NewDoNothingApp(appmgr, &am)
case appv1alpha1.InstallFailed:
return appstate.NewInstallFailedApp(appmgr, &am)
case appv1alpha1.PendingCancelFailed:
return appstate.NewPendingCancelFailedApp(appmgr, &am)
case appv1alpha1.DownloadingCancelFailed:
Expand Down
Loading