client-go gin的简单整合七-继续完善

背景:

紧接上文:client-go gin的简单整合六-list-watch二(关于Rs与Pod以及Deployment的完善),继续去完善相关的event 以及显示pod ip等相关配置还要继续搞一下指定deployment name显示相关pod信息!

client-go gin的简单整合七-继续完善

为什么要加一下event呢?

举一个例子

cat nginx3.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx3
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        command: ["/abc"]
        resources: {}
status: {}
[zhangpeng@zhangpeng k8s]$ kubectl apply -f nginx3.yaml 
deployment.apps/nginx3 created
[zhangpeng@zhangpeng k8s]$ kubectl get pods -o wide
NAME                      READY   STATUS             RESTARTS      AGE   IP            NODE    NOMINATED NODE   READINESS GATES
nginx-85b98978db-xk7kc    1/1     Running            0             21d   10.244.1.22   k8s-2   <none>           <none>
nginx1-85b98978db-wmvck   1/1     Running            0             28h   10.244.1.29   k8s-2   <none>           <none>
nginx2-6b5fb95cd4-77lk5   1/1     Running            0             29h   10.244.1.27   k8s-2   <none>           <none>
nginx3-9df8ff7bf-mjb2g    0/1     CrashLoopBackOff   1 (17s ago)   50s   10.244.1.32   k8s-2   <none>           <none>

image.png

but!访问:http://127.0.0.1:8080/deployments?ns=default(上一节运行的main.go依然在运行前提)

image.png

为什么pod明明CrashLoopBackOff 了但是他还显示running......

参照:https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/

image.png

image.png

解决方式:

想到的是判断pod contonditions中status是否为True,如果不是true则打印message字段,写一个方法:

/src/service/PodUtil.go

package service

import v1 "k8s.io/api/core/v1"

func GetPodMessage(pod v1.Pod) string {
	message := ""
	for _, contition := range pod.Status.Conditions {
		if contition.Status != "True" {
			message += contition.Message
		}
	}
	return message
}

Pod的struct ,添加对应字段Message:

/src/service/Pod.go

package service

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"k8s-demo1/src/core"
	. "k8s-demo1/src/lib"
	v1 "k8s.io/api/apps/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type Pod struct {
	Namespace  string
	Name       string
	Status     string
	Images     string
	NodeName   string
	CreateTime string
	Message    string
	Labels     map[string]string
}

func ListallPod(g *gin.Context) {
	ns := g.Query("ns")

	//pods, err := K8sClient.CoreV1().Pods(ns).List(context.Background(), metav1.ListOptions{})
	pods, err := core.PodMap.ListByNS(ns)
	if err != nil {
		g.Error(err)
	}
	ret := make([]*Pod, 0)
	for _, item := range pods {

		ret = append(ret, &Pod{
			Namespace:  item.Namespace,
			Name:       item.Name,
			Status:     string(item.Status.Phase),
			Labels:     item.Labels,
			NodeName:   item.Spec.NodeName,
			Images:     item.Spec.Containers[0].Image,
			Message:    GetPodMessage(*item),
			CreateTime: item.CreationTimestamp.Format("2006-01-02 15:04:05"),
		})

	}
	g.JSON(200, ret)
	return
}

/src/service/Deployment.go

package service

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"k8s-demo1/src/core"
	v1 "k8s.io/api/apps/v1"
	"log"
)

type Deployment struct {
	Namespace           string
	Name                string
	Replicas            int32
	AvailableReplicas   int32
	UnavailableReplicas int32
	Images              string
	CreateTime          string
	Labels              map[string]string
	Pods                []*Pod
}

func ListDeployment(g *gin.Context) {
	ns := g.Query("ns")
	deplist, _ := core.DepMap.ListByNS(ns)
	//dps, err := K8sClient.AppsV1().Deployments(ns).List(context.Background(), metav1.ListOptions{})
	//if err != nil {
	//	g.Error(err)
	//}
	ret := make([]*Deployment, 0)
	for _, item := range deplist {
		ret = append(ret, &Deployment{
			Namespace:           item.Namespace,
			Name:                item.Name,
			Replicas:            item.Status.Replicas,
			AvailableReplicas:   item.Status.AvailableReplicas,
			UnavailableReplicas: item.Status.UnavailableReplicas,
			Images:              item.Spec.Template.Spec.Containers[0].Image,
			Labels:              item.GetLabels(),
			Pods:                GetPodsByDep(*item),
			CreateTime:          item.CreationTimestamp.Format("2006-01-02 15:03:04"),
		})

	}
	g.JSON(200, ret)
	return
}

func GetLabels(m map[string]string) string {
	labels := ""
	// aa=xxx,xxx=xx
	for k, v := range m {
		if labels != "" {
			labels += ","
		}
		labels += fmt.Sprintf("%s=%s", k, v)
	}
	return labels
}
func GetPodsByDep(dep v1.Deployment) []*Pod {
	rsLabelsMap, err := core.RSMap.GetRsLabelsByDeployment(&dep)
	if err != nil {
		log.Fatal(err)
	}

	pods, err := core.PodMap.ListByRsLabels(dep.Namespace, rsLabelsMap)
	if err != nil {
		log.Fatal(err)
	}
	ret := make([]*Pod, 0)

	for _, pod := range pods {
		if core.RSMap.GetRsLabelsByDeploymentname(&dep) == pod.OwnerReferences[0].Name {
			ret = append(ret, &Pod{
				Name:       pod.Name,
				Namespace:  pod.Namespace,
				Images:     pod.Spec.Containers[0].Image,
				NodeName:   pod.Spec.NodeName,
				Labels:     pod.Labels,
				Status:     string(pod.Status.Phase),
				Message:    GetPodMessage(*pod),
				CreateTime: pod.CreationTimestamp.Format("2006-01-02 15:04:05"),
			})
		}
	}
	return ret
}

运行mai.go

http://127.0.0.1:8080/deployments?ns=default

image.png

http://127.0.0.1:8080/pods?ns=default

image.png

list-watch实现一下event

注:抄来的,还要消化一下

/src/core/event_int.go

package core

import (
	"fmt"
	v1 "k8s.io/api/core/v1"
	"sync"
)

var EventMap *EventMapStruct

type EventMapStruct struct {
	data sync.Map
}

func (eventmap EventMapStruct) GetMessage(ns string, kind string, name string) string {
	key := fmt.Sprintf("%s-%s-%s", ns, kind, name)
	if v, ok := eventmap.data.Load(key); ok {
		return v.(*v1.Event).Message
	}
	return ""
}

type EventHandler struct{}

func (eventmap *EventHandler) storeData(obj interface{}, isDelete bool) {
	if event, ok := obj.(*v1.Event); ok {
		key := fmt.Sprintf("%s-%s-%s", event.Namespace, event.InvolvedObject.Kind, event.InvolvedObject.Name)
		if !isDelete {
			EventMap.data.Store(key, event)
		} else {
			EventMap.data.Delete(key)
		}
	}
}

func (eventmap *EventHandler) OnAdd(obj interface{}) {
	eventmap.storeData(obj, false)
}

func (eventmap *EventHandler) OnUpdate(oldObj, newObj interface{}) {
	eventmap.storeData(newObj, false)
}

func (eventmap *EventHandler) OnDelete(obj interface{}) {
	eventmap.storeData(obj, true)
}

func init() {
	EventMap = &EventMapStruct{}
}

在/src/core/deployment_int.go int初始化中添加eventInformer:

func InitDeployment() {
	factory := informers.NewSharedInformerFactory(lib.K8sClient, 0)
	depinformer := factory.Apps().V1().Deployments()
	depinformer.Informer().AddEventHandler(&DepHandler{})
	Podinformer := factory.Core().V1().Pods()
	Podinformer.Informer().AddEventHandler(&PodHandler{})
	Rsinformer := factory.Apps().V1().ReplicaSets()
	Rsinformer.Informer().AddEventHandler(&RSHandler{})
	eventInformer := factory.Core().V1().Events()
	eventInformer.Informer().AddEventHandler(&EventHandler{})
	factory.Start(wait.NeverStop)
}

/src/service/Pod.go

package service

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"k8s-demo1/src/core"
	. "k8s-demo1/src/lib"
	v1 "k8s.io/api/apps/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type Pod struct {
	Namespace  string
	Name       string
	Status     string
	Images     string
	NodeName   string
	CreateTime string
	//IsReady    bool
	Message      string
	HostIp       string
	PodIp        string
	RestartCount int32
	Labels       map[string]string
}

func ListallPod(g *gin.Context) {
	ns := g.Query("ns")

	//pods, err := K8sClient.CoreV1().Pods(ns).List(context.Background(), metav1.ListOptions{})
	pods, err := core.PodMap.ListByNS(ns)
	if err != nil {
		g.Error(err)
	}
	ret := make([]*Pod, 0)
	for _, item := range pods {

		ret = append(ret, &Pod{
			Namespace: item.Namespace,
			Name:      item.Name,
			Status:    string(item.Status.Phase),
			Labels:    item.Labels,
			NodeName:  item.Spec.NodeName,
			Images:    item.Spec.Containers[0].Image,
			//IsReady:   GetPodIsReady(*item),
			//Message: GetPodMessage(*item),
			Message:      core.EventMap.GetMessage(item.Namespace, "Pod", item.Name),
			HostIp:       item.Status.HostIP,
			PodIp:        item.Status.PodIP,
			RestartCount: item.Status.ContainerStatuses[0].RestartCount,
			CreateTime:   item.CreationTimestamp.Format("2006-01-02 15:04:05"),
		})

	}
	g.JSON(200, ret)
	return
}
func ListPodsByLabel(ns string, labels []map[string]string) (ret []*Pod) {
	list, err := core.PodMap.ListByRsLabels(ns, labels)
	if err != nil {
		return nil
	}

	for _, item := range list {
		ret = append(ret, &Pod{
			Name:      item.Name,
			Namespace: item.Namespace,
			Images:    item.Spec.Containers[0].Image,
			NodeName:  item.Spec.NodeName,
			Status:    string(item.Status.Phase),
			//Message: GetPodMessage(*item),
			Message:      core.EventMap.GetMessage(item.Namespace, "Pod", item.Name),
			RestartCount: item.Status.ContainerStatuses[0].RestartCount,
			CreateTime:   item.CreationTimestamp.Format("2006-01-02 15:22:33"),
		})
	}

	return
}

image.png

/src/deployment/Deployment.go中Message也可以修改一下:

package service

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"k8s-demo1/src/core"
	v1 "k8s.io/api/apps/v1"
	"log"
)

type Deployment struct {
	Namespace           string
	Name                string
	Replicas            int32
	AvailableReplicas   int32
	UnavailableReplicas int32
	Images              string
	CreateTime          string
	Labels              map[string]string
	Pods                []*Pod
}

func ListDeployment(g *gin.Context) {
	ns := g.Query("ns")
	deplist, _ := core.DepMap.ListByNS(ns)
	//dps, err := K8sClient.AppsV1().Deployments(ns).List(context.Background(), metav1.ListOptions{})
	//if err != nil {
	//	g.Error(err)
	//}
	ret := make([]*Deployment, 0)
	for _, item := range deplist {
		ret = append(ret, &Deployment{
			Namespace:           item.Namespace,
			Name:                item.Name,
			Replicas:            item.Status.Replicas,
			AvailableReplicas:   item.Status.AvailableReplicas,
			UnavailableReplicas: item.Status.UnavailableReplicas,
			Images:              item.Spec.Template.Spec.Containers[0].Image,
			Labels:              item.GetLabels(),
			Pods:                GetPodsByDep(*item),
			CreateTime:          item.CreationTimestamp.Format("2006-01-02 15:03:04"),
		})

	}
	g.JSON(200, ret)
	return
}

func GetLabels(m map[string]string) string {
	labels := ""
	// aa=xxx,xxx=xx

	for k, v := range m {
		if labels != "" {
			labels += ","
		}
		labels += fmt.Sprintf("%s=%s", k, v)
	}
	return labels
}
func GetPodsByDep(dep v1.Deployment) []*Pod {
	rsLabelsMap, err := core.RSMap.GetRsLabelsByDeployment(&dep)
	if err != nil {
		log.Fatal(err)
	}

	pods, err := core.PodMap.ListByRsLabels(dep.Namespace, rsLabelsMap)
	if err != nil {
		log.Fatal(err)
	}
	ret := make([]*Pod, 0)

	for _, pod := range pods {
		if core.RSMap.GetRsLabelsByDeploymentname(&dep) == pod.OwnerReferences[0].Name {
			ret = append(ret, &Pod{
				Name:      pod.Name,
				Namespace: pod.Namespace,
				Images:    pod.Spec.Containers[0].Image,
				NodeName:  pod.Spec.NodeName,
				Labels:    pod.Labels,
				Status:    string(pod.Status.Phase),
				//IsReady:   GetPodIsReady(*pod),
				//	Message:    GetPodMessage(*pod),
				Message:      core.EventMap.GetMessage(pod.Namespace,"Pod",pod.Name),
				HostIp:       pod.Status.HostIP,
				PodIp:        pod.Status.PodIP,
				RestartCount: pod.Status.ContainerStatuses[0].RestartCount,
				CreateTime:   pod.CreationTimestamp.Format("2006-01-02 15:04:05"),
			})
		}
	}
	return ret
}

关于Pod IP

[zhangpeng@zhangpeng k8s]$ kubectl edit pod nginx1-85b98978db-wmvck

image.png

/src/service/Pod.go

package service

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"k8s-demo1/src/core"
	. "k8s-demo1/src/lib"
	v1 "k8s.io/api/apps/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type Pod struct {
	Namespace  string
	Name       string
	Status     string
	Images     string
	NodeName   string
	CreateTime string
	Message    string
	HostIp     string
	PodIp      string
	Labels     map[string]string
}

func ListallPod(g *gin.Context) {
	ns := g.Query("ns")

	//pods, err := K8sClient.CoreV1().Pods(ns).List(context.Background(), metav1.ListOptions{})
	pods, err := core.PodMap.ListByNS(ns)
	if err != nil {
		g.Error(err)
	}
	ret := make([]*Pod, 0)
	for _, item := range pods {

		ret = append(ret, &Pod{
			Namespace: item.Namespace,
			Name:      item.Name,
			Status:    string(item.Status.Phase),
			Labels:    item.Labels,
			NodeName:  item.Spec.NodeName,
			Images:    item.Spec.Containers[0].Image,
			Message:    GetPodMessage(*item),
			HostIp:     item.Status.HostIP,
			PodIp:      item.Status.PodIP,
			CreateTime: item.CreationTimestamp.Format("2006-01-02 15:04:05"),
		})

	}
	g.JSON(200, ret)
	return
}
func ListPodsByLabel(ns string, labels []map[string]string) (ret []*Pod) {
	list, err := core.PodMap.ListByRsLabels(ns, labels)
	if err != nil {
		return nil
	}

	for _, item := range list {
		ret = append(ret, &Pod{
			Name:      item.Name,
			Namespace: item.Namespace,
			Images:    item.Spec.Containers[0].Image,
			NodeName:  item.Spec.NodeName,
			Status:    string(item.Status.Phase),
			//Message: GetPodMessage(*item),
			Message:    core.EventMap.GetMessage(item.Namespace, "Pod", item.Name),
			CreateTime: item.CreationTimestamp.Format("2006-01-02 15:22:33"),
		})
	}

	return
}

/src/service/Deployment.go

package service

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"k8s-demo1/src/core"
	v1 "k8s.io/api/apps/v1"
	"log"
)

type Deployment struct {
	Namespace           string
	Name                string
	Replicas            int32
	AvailableReplicas   int32
	UnavailableReplicas int32
	Images              string
	CreateTime          string
	Labels              map[string]string
	Pods                []*Pod
}

func ListDeployment(g *gin.Context) {
	ns := g.Query("ns")
	deplist, _ := core.DepMap.ListByNS(ns)
	//dps, err := K8sClient.AppsV1().Deployments(ns).List(context.Background(), metav1.ListOptions{})
	//if err != nil {
	//	g.Error(err)
	//}
	ret := make([]*Deployment, 0)
	for _, item := range deplist {
		ret = append(ret, &Deployment{
			Namespace:           item.Namespace,
			Name:                item.Name,
			Replicas:            item.Status.Replicas,
			AvailableReplicas:   item.Status.AvailableReplicas,
			UnavailableReplicas: item.Status.UnavailableReplicas,
			Images:              item.Spec.Template.Spec.Containers[0].Image,
			Labels:              item.GetLabels(),
			Pods:                GetPodsByDep(*item),
			CreateTime:          item.CreationTimestamp.Format("2006-01-02 15:03:04"),
		})

	}
	g.JSON(200, ret)
	return
}

func GetLabels(m map[string]string) string {
	labels := ""
	// aa=xxx,xxx=xx

	for k, v := range m {
		if labels != "" {
			labels += ","
		}
		labels += fmt.Sprintf("%s=%s", k, v)
	}
	return labels
}
func GetPodsByDep(dep v1.Deployment) []*Pod {
	rsLabelsMap, err := core.RSMap.GetRsLabelsByDeployment(&dep)
	if err != nil {
		log.Fatal(err)
	}

	pods, err := core.PodMap.ListByRsLabels(dep.Namespace, rsLabelsMap)
	if err != nil {
		log.Fatal(err)
	}
	ret := make([]*Pod, 0)

	for _, pod := range pods {
		if core.RSMap.GetRsLabelsByDeploymentname(&dep) == pod.OwnerReferences[0].Name {
			ret = append(ret, &Pod{
				Name:      pod.Name,
				Namespace: pod.Namespace,
				Images:    pod.Spec.Containers[0].Image,
				NodeName:  pod.Spec.NodeName,
				Labels:    pod.Labels,
				Status:    string(pod.Status.Phase),
				Message:    GetPodMessage(*pod),
				HostIp:     pod.Status.HostIP,
				PodIp:      pod.Status.PodIP,
				CreateTime: pod.CreationTimestamp.Format("2006-01-02 15:04:05"),
			})
		}
	}
	return ret
}

http://127.0.0.1:8080/deployments?ns=default

image.png
http://127.0.0.1:8080/pods?ns=default

image.png

Pod重启次数

[zhangpeng@zhangpeng k8s]$ kubectl edit pod nginx3-9df8ff7bf-mzddn

image.png

/src/service/Pod.go,Pod struct增加RestartCount int32,取值字段item.Status.ContainerStatuses0.RestartCount,如下(多个容器后面是不是要考虑循环取值?以后在说吧......):

type Pod struct {
	Namespace  string
	Name       string
	Status     string
	Images     string
	NodeName   string
	CreateTime string
	//IsReady    bool
	Message      string
	HostIp       string
	PodIp        string
	RestartCount int32
	Labels       map[string]string
}
func ListallPod(g *gin.Context) {
	ns := g.Query("ns")

	//pods, err := K8sClient.CoreV1().Pods(ns).List(context.Background(), metav1.ListOptions{})
	pods, err := core.PodMap.ListByNS(ns)
	if err != nil {
		g.Error(err)
	}
	ret := make([]*Pod, 0)
	for _, item := range pods {

		ret = append(ret, &Pod{
			Namespace: item.Namespace,
			Name:      item.Name,
			Status:    string(item.Status.Phase),
			Labels:    item.Labels,
			NodeName:  item.Spec.NodeName,
			Images:    item.Spec.Containers[0].Image,
			//IsReady:   GetPodIsReady(*item),
			Message: GetPodMessage(*item),
			//Message:    core.EventMap.GetMessage(item.Namespace, "Pod", item.Name),
			HostIp:       item.Status.HostIP,
			PodIp:        item.Status.PodIP,
			RestartCount: item.Status.ContainerStatuses[0].RestartCount,
			CreateTime:   item.CreationTimestamp.Format("2006-01-02 15:04:05"),
		})

	}
	g.JSON(200, ret)
	return
}

image.png

接下来的问题:

先删除nginx3 deployment:

[zhangpeng@zhangpeng k8s]$ kubectl delete -f nginx3.yaml 
deployment.apps "nginx3" deleted

创建一个正常的nginx3.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx3
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}
[zhangpeng@zhangpeng k8s]$ kubectl apply -f nginx3.yaml 
deployment.apps/nginx3 created
[zhangpeng@zhangpeng k8s]$ kubectl get pods
NAME                      READY   STATUS              RESTARTS   AGE
nginx-85b98978db-xk7kc    1/1     Running             0          23d
nginx1-85b98978db-wmvck   1/1     Running             0          3d23h
nginx2-6b5fb95cd4-77lk5   1/1     Running             0          4d
nginx3-6f97cd4f65-k7ffx   0/1     ContainerCreating   0          4s

image.png
[zhangpeng@zhangpeng k8s]$ cp nginx3.yaml nginx33.yaml

vim nginx33.yaml继续创建一个无法成功启动的Pod:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx3
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        command: ["/abc"]
        resources: {}
status: {}
[zhangpeng@zhangpeng k8s]$ kubectl apply -f nginx33.yaml 
deployment.apps/nginx3 configured

image.png

but:

image.png

恩 我这里做的还是有问题,deployment中数量显示了 但是没有能显示那个没有成功的pod......(貌似只有重启后才发现最新的,但是也还是显示一个......).这里没有想好怎么处理......也希望有大佬能给指点迷津!

总结:

  1. event实现了list watch
  2. ip restartcount如何在pod中获取
  3. 怎么样显示nginx3示例中两个pod?要好好想一下!

原文地址:https://cloud.tencent.com/developer/article/2022740

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340