[ Cmii ] [ Octopus ] - 优化项目结构

This commit is contained in:
zeaslity
2024-03-19 16:04:09 +08:00
committed by zeaslity
parent 4ca8d77e74
commit 6b4616690c
80 changed files with 979 additions and 1025 deletions

View File

@@ -0,0 +1,127 @@
package agent_operator
var CmiiBackendAppMap = map[string]string{
"cmii-admin-data": "5.2.0",
"cmii-admin-gateway": "5.2.0",
"cmii-admin-user": "5.2.0",
"cmii-app-release": "4.2.0-validation",
"cmii-open-gateway": "5.2.0",
"cmii-suav-supervision": "5.2.0",
"cmii-uav-airspace": "5.2.0",
"cmii-uav-alarm": "5.2.0",
"cmii-uav-autowaypoint": "4.1.6-cm-0828",
"cmii-uav-brain": "5.2.0",
"cmii-uav-cloud-live": "5.2.0",
"cmii-uav-clusters": "5.2.0",
"cmii-uav-cms": "5.2.0",
"cmii-uav-data-post-process": "5.2.0",
"cmii-uav-depotautoreturn": "4.2.0",
"cmii-uav-developer": "5.2.0-25858",
"cmii-uav-device": "5.2.0",
"cmii-uav-emergency": "5.2.0",
"cmii-uav-gateway": "5.2.0",
"cmii-uav-industrial-portfolio": "5.2.0-25268-10",
"cmii-uav-integration": "5.2.0-25447",
"cmii-uav-kpi-monitor": "5.2.0",
"cmii-uav-logger": "5.2.0",
"cmii-uav-material-warehouse": "5.2.0",
"cmii-uav-mission": "5.2.0-25840",
"cmii-uav-mqtthandler": "5.2.0-25340",
"cmii-uav-notice": "5.2.0",
"cmii-uav-oauth": "5.2.0",
"cmii-uav-process": "5.2.0",
"cmii-uav-surveillance": "5.2.0-25854",
"cmii-uav-threedsimulation": "5.2.0",
"cmii-uav-tower": "5.2.0",
"cmii-uav-user": "5.2.0",
"cmii-uav-waypoint": "5.2.0",
}
var CmiiFrontendAppMap = map[string]string{
"cmii-suav-platform-supervision": "5.2.0",
"cmii-suav-platform-supervisionh5": "5.2.0",
"cmii-uav-platform": "5.2.0-011004",
"cmii-uav-platform-ai-brain": "5.2.0",
"cmii-uav-platform-armypeople": "5.2.0-24538",
"cmii-uav-platform-base": "5.2.0",
"cmii-uav-platform-cms-portal": "5.2.0",
"cmii-uav-platform-detection": "5.2.0",
"cmii-uav-platform-emergency-rescue": "5.2.0",
"cmii-uav-platform-hljtt": "5.2.0",
"cmii-uav-platform-jiangsuwenlv": "4.1.3-jiangsu-0427",
"cmii-uav-platform-logistics": "5.2.0",
"cmii-uav-platform-media": "5.2.0",
"cmii-uav-platform-multiterminal": "5.2.0",
"cmii-uav-platform-mws": "5.2.0",
"cmii-uav-platform-oms": "5.2.0",
"cmii-uav-platform-open": "5.2.0",
"cmii-uav-platform-qingdao": "4.1.6-24238-qingdao",
"cmii-uav-platform-qinghaitourism": "4.1.0-21377-0508",
"cmii-uav-platform-security": "4.1.6",
"cmii-uav-platform-securityh5": "5.2.0",
"cmii-uav-platform-seniclive": "5.2.0",
"cmii-uav-platform-share": "5.2.0",
"cmii-uav-platform-splice": "5.2.0",
"cmii-uav-platform-threedsimulation": "5.2.0-21392",
"cmii-uav-platform-visualization": "5.2.0",
}
var CmiiMiddlewareNameMap = map[string]string{
"helm-nacos": "single",
"helm-emqxs": "single",
"helm-mysql": "single",
"helm-redis": "replication",
"helm-rabbitmq": "single",
}
var CmiiSrsAppMap = map[string]string{
"helm-live-op-v2": "deployment",
"helm-live-rtsp-op": "4.1.6",
"helm-live-srs-rtc": "statefulset",
}
var CmiiGISAppMap = map[string]string{
"cmii-uav-gis-server": "5.4.0",
"cmii-uav-grid-datasource": "5.4.0",
"cmii-uav-grid-engine": "5.4.0",
"cmii-uav-grid-manage": "5.4.0",
}
var CmiiDevK8sConfig = `apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeE1ERXhPREEyTURZeU5Gb1hEVE14TURFeE5qQTJNRFl5TkZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBS2ZNCjFjTjBNUnhUTkRGdEZxcnRIZ0RPM29SV0dicmVob3VFcDJ3VUVRbU8yRUFyZDdkMUFReTJsSm9WM0RUVmhXbUwKcUFUOFcxaWRaS0x0Wm5mNjEva3JPeDd0U2lJeU4xa1ErN3NYRUhnTjVMc01EOVlKcndpUFdFY2FXdU9HVmI1aApMWDZWOTRjN0U5UlFDOENtd09iSkRCNG45ZE8zcDVlTDJHaFRpMkNrRWt3ZkRPR0tEL1IxeUNaK0tFcDRWWlplCnpwcnUzRG5zOUNqZHVOT1VBWTZzUGxjazNvdEdIVnhnRC9IRlRjUEhNbGhvUVQ4dmNDOTZwc0FtYXZPR1BZQ0YKa3RtN0VWYkZDOHN5Q1BMT3AwWWhTWHRkbGtKaC9UWHBaM0hSUWJxSzVPNXR4K1dGL05qMGJVc202ZldSMzZWQgpKQVVscUJIeFhSTzhGTFNrVHkwQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFKeWZ2T3hHVVYvT2wybGRQNnYxeWFSTkd5RVkKWkVxTmM2Y29LSklsd0VQNUxNYzdZNGFReWorZCtVTE4zYmIrOXZsZXdHamluTHRrUW5HZ1R3Q3pKTU5ZNlNJNQo2NzJGZEtQTE85Szdpalhway9qRE9FVHJWS25aMXJBTytOUVBmSVhpcXQ3Y1RyVHlaVzdKTVl3emZNa2VlTGErCnREdmY1Rm5vQTBLN2U3a0ZXNTBpN2pXcGh4RXRMNEJpNzAwNnU4NEpqTU5weVp1MzhKMjFXZkR1RjBoU0NQREgKS0x4cnZIZ0FOYzJWU1c2L3JPaVVCQjdiV0JkcWcyQUNVRWZwN0V3UGs2S1BsdGNiNTJtdFhCU2xiQ3pRWWw4UQpmNmVGRFIrbnRjeXNGbU1FMFI3M1lNSHJwR0dGdlduSDVaTmEyVEJYdHpwN2tNNkVPREE5a2R4WkI1dz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
server: https://192.168.11.170:16443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4ekNDQWR1Z0F3SUJBZ0lKQU9SWThQZlhadWQyTUEwR0NTcUdTSWIzRFFFQkN3VUFNQlV4RXpBUkJnTlYKQkFNVENtdDFZbVZ5Ym1WMFpYTXdIaGNOTWpJd01URTRNRFl6TmpRMFdoY05Nekl3TVRFMk1EWXpOalEwV2pBMApNUmN3RlFZRFZRUUtEQTV6ZVhOMFpXMDZiV0Z6ZEdWeWN6RVpNQmNHQTFVRUF3d1FhM1ZpWlhKdVpYUmxjeTFoClpHMXBiakNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFPNTZ0ZG51M24rWUsxM3oKZmNlTzNiSmhBL2J0SGpoQXpvRnNObmZjeEY3dlRTZGczSUxySmVNVkFGbG50MHpUL2xacFBlU0ZUN25iL1g1Ygo4RjErSHA2dVR0b0hRVGJHR2VzbEprdkpFMjB3OGJ0Z3VrdlNmTnROOS9NNlFTWWkvTGlHeTZpd2kveGdBVUtKClFtVW1vZmhZSHNKMllFbXJCcExOVFhtenl2a2lUTlJZVC9iNlJJRzNiT3lIVm1Lc1cwQkNQNVZTTFJsLzErZlMKM0dCUUZ2UTNXdTdmVWlzMW9DSXhsc1k5V2VJUmpGOWJDbWtKNnZsT3BWbGlsTlA0cEtSSnl4aXNBNzExNENNWAprRGJvRFBXb2lxMktubzYveXI2L0xwMktsVVVSa1JhQklodEl5eXV2TldPbjhiTW90SUpCNWNOems4UkxYTm5TCklPZEtMVDhDQXdFQUFhTW5NQ1V3RGdZRFZSMFBBUUgvQkFRREFnV2dNQk1HQTFVZEpRUU1NQW9HQ0NzR0FRVUYKQndNQ01BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1lwVk9NemlGRUFta1A4S3B2ZWttR3laVGV3dzQreVhyUwo3TEpoWTdTR2pGY210ZldMSW9PWEhmWmZlZWNsN3M5Snh1SytPZlhqU0d0UU9jWXk0WHo5OVFWY2FRandJMEg5Cnc3aWJiYUw3M093RGZrRDMrdlNhME9ZRWZKSFlsNXErQXBnQVpLVWRWazMvZHpJSmhRR0V6L0UxcjdYTlNabDUKL1hOT3pwbzl0VHV2dDAxRlllV0RMN01DeWZGRHFTelpQdnNyWW81bDFiTE5yeEZHb1dvSTdUMlJzR205VXJyYwoyTy84R2hMYTkwZ2tLeE9JTEpYdlJCY2RrOUN4N01ROGFGVHBuSmtPMXJzVzUxMTFoTG5hNm9WRHhISlVrbjRkCmNhODFDV3R1Yk44dkpSYlFwVmkySTJ5K3ljZ3lrNTMzR21GQXNVS3dkdm5rVjNqTVJVbFYKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcGdJQkFBS0NBUUVBN25xMTJlN2VmNWdyWGZOOXg0N2RzbUVEOXUwZU9FRE9nV3cyZDl6RVh1OU5KMkRjCmd1c2w0eFVBV1dlM1ROUCtWbWs5NUlWUHVkdjlmbHZ3WFg0ZW5xNU8yZ2RCTnNZWjZ5VW1TOGtUYlREeHUyQzYKUzlKODIwMzM4enBCSmlMOHVJYkxxTENML0dBQlFvbENaU2FoK0ZnZXduWmdTYXNHa3MxTmViUEsrU0pNMUZoUAo5dnBFZ2JkczdJZFdZcXhiUUVJL2xWSXRHWC9YNTlMY1lGQVc5RGRhN3Q5U0t6V2dJakdXeGoxWjRoR01YMXNLCmFRbnErVTZsV1dLVTAvaWtwRW5MR0t3RHZYWGdJeGVRTnVnTTlhaUtyWXFlanIvS3ZyOHVuWXFWUlJHUkZvRWkKRzBqTEs2ODFZNmZ4c3lpMGdrSGx3M09UeEV0YzJkSWc1MG90UHdJREFRQUJBb0lCQVFDdTE5YldGbFNZdGNjdAoxYVJsRi9DZ3BKSlVpcHA2WWNGRmtFSUs5UmdnQmxESnl6RkE1d2hiQ2YyOGp0Y01BKzFZQzBidWNYTDNjRHZWClZiRFB5dlRHSUVQOWhBNGpDM0RiUHR4cCtkMDlWQUlYQUI3MkVqZXFUZXE1TC8rdDV6N2tSeWV2NE9oeE95NFIKU3pNYm1BeHVXS1VNcTkrQ2cxcUpiTzRkaVYwSjg5cUtidExsclFCeDFxcHNnUjNES1VhVGVNKzVpeFYyQ1Y1bApSNDV4aU43NWRrSkpaZlY2UUV5K3V2UVd0VHk4NUN3R1U2T2hjOXA4d2s0MmFrQS9qM05FTUZiTjdDaDFKbi9RCjRhNUJpMituRUE4dGVvV2FRSzdoeU5CRENWbTFsamFjaFFveGRSNGhCWVUxdkhTbkt4a0c4bDA1K1BpRTZmZFkKaUtyemhGR0JBb0dCQVBwOStKTExzZXJ6dFQ4a2VLU2FSMXBMOHB5MTQ3cmdjdEVhckxJL2ZqY1VMU3c3OUk3UAovWWhIWnhmdm9TZEZ2QTZwNy81eHFCRitaNTM5L1NKNDlLeWFOdGNJbW01UTZKSW9aRGgzWmVVS3lMKzA1YTdRCkNqMU1wZ2hKMlZDT2VPamNxd0NVQkFhcjNWSjd0cXRxRVFCQk9jMnlWU3dzbU5wclMyYmU1S3RCQW9HQkFQTzUKSG9ZVTBMK2tzdzJKUVM5ODF1ZWtrbDMzR1ZWQ2dPUFdGWThhR3VGRGt3Sm84WGk2TmhtKzh2TjlNaGg3WkYzeQpTU3E1U2RJd01pR0IvKzVJaWp1V25DbWszY2RPdGU0VFBsZHFvdjc3Q1FUUmxPNWJCekR0L1VqYVBBam5GS0FpClg4K0V6NUVXOXFSclN2ZXplZHFDRVRBVDhRWThqNk1WY0VCRW96aC9Bb0dCQUphcVRHZ25RdVdhSHF0VENZbWcKRGtqZW81Zmt3NHcwMG5xNWU2UmZFbENZdnk3N0JQY2RYVmFwOC9WdXVkVEFXZ1BMN1VGekpXOFlROFRBNzQvYgpodmVHYm5QYWhlRFNvNEM5OE1JUjl1VFVIcmxJV2xwU1ljWkxJeGFiTEs0S2MrbEVTVXE0dk04eWNwWFpPWjlTCjFkVDhab00xdjRzcGErcjhYRWNNekNmQkFvR0JBSXVuaXI4SDFHbk1CVEYvY1pPMWRDczkyUVR3MzFwRWhqaUgKWnNrZUMwTURCb3o5OTBmWFk4S3k4T0htM2pxN0VkTG5UMWVrM3BFTFB0NkdjRkZvelpUQmczQTFZVU9nYlkwagpCN2p0aU1LVXRDRkh1cEF1SnR1NXMwWDRqeWdHeVlITTBKdkhuV3lrL09WUCthQWYvblhmeTl1QndiMXlIRmcxCm82R2Y4dXNmQW9HQkFKeGlQcGdDODJPckoxazE3V3dyOFI2ZXpxR2VYb0JPRzFlOEN6ZG1UbWFrN3prWDJJelEKSTVjT3dGaTlnREhTbUVMa0dYZnRHZ01EcXF1VHVLdS9OdW9DQS94Z2FrdTQvVHplNktqbzRjc0NDTmFza3VrRQozYnhwSnU5cElYRU5tMXVuNXBZRy90QTF0V1Rtc3dnRjY1anc2RFpTQUFUTFZMSXg3RVRDR0RlOQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=`
var CmiiCoreK8sConfig = `apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJd01URXhOakUwTURJd09Wb1hEVE13TVRFeE5ERTBNREl3T1Zvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTEZhCjV4N0M2MisrZjA5UXUzVWR6UUFXRDN4NDRkTVV6bkxvTjc5Y0RTbzduYjhTd0JmMzk2aFEwaEdiT2lDUXhLc1IKczJhcXl2N0dLUXAvdTVNbUU0bXF1YWEybE1yUkc1UWFJOWhHNlp5SDdxYkFlU0dZSVplZGVoMWF6bzVnblBWRwoyck5aVWR3WU5tUXYvemF6V3dSbi9QQUNuNEt4MkxjYVVJUm16YkZHRnJ2VXl3UDl4UTc2MlNvRWZoMENycEpvCmltTHR3ZGFOU3dweGRCTFpkcXlRY05xRVV0dUI2VXVVM0Z3Y2FBckJpNTZ1OTFJbHVEWS9Dd1UyeDJCSHR1WkwKR2RuQUM0c1VhWm9oZzRFZ0U3UEp6RnFXTUtyaGRmekRzc05EK1VhV2sxRmhvRzViVWZiQ051Zy9KUnNlRzJBZQpodjAvU1ZNcSs5WWYyR0dheC9NQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFGdVYxK3Z4UGVrUm82T2U2YTI4NmFHQjduWG0KMUlGVllwSWUxeTVoZy9aTlhKN1RndXFPb2Zjc3JnZ1h2MmdaQkdFN0pheTM0SkhuRFB3Y3ZCMzhHQUxtZmZWeAo2THJVN2ZtSWlpajRIc1NyaHRrMWQzcmhjdFkwMEw2dGJMMzVvTWJnUGwzSERUbGh0M0wxM0gvUVFScXR3TXFOCnBHeWk3VWprbFNpNWVsRWJrbnlUUy9OWTA1Y1JyMTU2N0p4N3F3QlpmUlZaZURUOHdidHpMZ05UWlFZRzVoM2EKQmp6dnlINFoyR2YrNnM4aXZlbGFUMjdPbGpOUTJvUUdyenhHV0ErZGJKSzNIdDVRRkVCeDdVaEsrNWtwYXViNwpWZTB1ekdGK1ZDb2ZFV2FtNk9CUFAycE51SW85d0Jsa24vbU9FUW5SU1FNMW15dmlIWHBaMnVKd1ozbz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
server: https://vip.ecs.io:6444
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4ekNDQWR1Z0F3SUJBZ0lKQU5ZM0hyTXZseUZjTUEwR0NTcUdTSWIzRFFFQkN3VUFNQlV4RXpBUkJnTlYKQkFNVENtdDFZbVZ5Ym1WMFpYTXdIaGNOTWpFd01URTFNRGd6T0RNNFdoY05NekV3TVRFek1EZ3pPRE00V2pBMApNUmN3RlFZRFZRUUtEQTV6ZVhOMFpXMDZiV0Z6ZEdWeWN6RVpNQmNHQTFVRUF3d1FhM1ZpWlhKdVpYUmxjeTFoClpHMXBiakNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFMS21TZDJIeVdYN2VTdnYKdS8yRnBZQWM5SWRBcFlQbmtESk5wR0Z1SEVlOUJWVXMyL1o3L3BQWGY3NTljVFdZUkV2V0dybDBNS1dTajhycAowQ2JTN3dvdkg2NnpTcWNKRDUzMW11OTgvaE0zenZzaTVqalIxOU5yTEFIL0QzbEZ6d2VnVHpNUWFvenNPc2VOCm0vNmI5cGRLNUcwYkNPRkJlZTRzeW1VdnVjT1NKblg5YkpZUnhNbVI5WHl3REowcnpTSHJrVE9ocVErUXYzdTAKMGZvVk9NSm9BdWkvR2JEV3ZpTEQrRmlDMnFJY0FYRGhNaGd2eVJwTFBPNFlZc0tCc2xjUVJwbkpjei9heFRBUQovM0c3T1pYWjJkNWVDQmRDY0pqL2orNlkyNVJsVXNDNDZzZWR1cTR0SGMrbEJ3UG5FSDYvTG53SUE0VHVaRXBpCkI3Q3RyU0VDQXdFQUFhTW5NQ1V3RGdZRFZSMFBBUUgvQkFRREFnV2dNQk1HQTFVZEpRUU1NQW9HQ0NzR0FRVUYKQndNQ01BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ0llSU0wSllLVjNiNUhISEdzMmV0eEt0VnQwaGNBTzNmcgpCcU5Ba3lPNkpvWkU2dnh3Nm5lQXNhc3V5RXh1NDFiMmlwYTJFdFlsTUNWbHE0anhjQWptMnU4b0xWb3NoWWIxClU4MkRqMkJuV2Z6TnhKV3dqSnQ5UzFhUXZmOXFxaDhueGJTeUVhNmxMZmEvTEpFQURzMDZNR05tQUJxbk5ZUVEKcEh1UnNXQlhwT3lSaWhtMHdlK21UNGwxYklMZ0Zpa2ZSaUw1WkRnWVlTNG9BRVpGY1NBbldKRFhSVTI0S0JIRQppYXk4SlNIcks1Ym12TWVpR1ZkL054WlhmSFdCcUcvZUI1SDRuaFhtVzhWbEdjQnhvdDBvckVta2FsblFpYnEwCnBWNUlwcXFBU3JjcjZnVUxrRmtvdWo1aG9rNWdIdWpqakFkenVSa3hyYTJiNERFa05jTTQKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBc3FaSjNZZkpaZnQ1SysrNy9ZV2xnQnowaDBDbGcrZVFNazJrWVc0Y1I3MEZWU3piCjluditrOWQvdm4xeE5aaEVTOVlhdVhRd3BaS1B5dW5RSnRMdkNpOGZyck5LcHdrUG5mV2E3M3orRXpmTyt5TG0KT05IWDAyc3NBZjhQZVVYUEI2QlBNeEJxak93Nng0MmIvcHYybDBya2JSc0k0VUY1N2l6S1pTKzV3NUltZGYxcwpsaEhFeVpIMWZMQU1uU3ZOSWV1Uk02R3BENUMvZTdUUitoVTR3bWdDNkw4WnNOYStJc1A0V0lMYW9od0JjT0V5CkdDL0pHa3M4N2hoaXdvR3lWeEJHbWNselA5ckZNQkQvY2JzNWxkblozbDRJRjBKd21QK1A3cGpibEdWU3dManEKeDUyNnJpMGR6NlVIQStjUWZyOHVmQWdEaE81a1NtSUhzSzJ0SVFJREFRQUJBb0lCQUdCam1EY09ySHQ1MDBjQgpja3kzYnpSUWF4OE9vajhwRVlRU29ENXhTcERxUzVaSlBlVWZ3WnZEQ2dtZFpSZWxzRE82c1hDZVlDRDFrdC9JCmg2WnE2TTUxM29KRCttTmxZQ2U1L0g1NjBodE1ZVURlODVoMG9CNVNGTXgrOGJwZEQvYnRaODRGYlhmYmZWdHQKN0Z6VGlaalhyNmV1am52NjkrNnAvQW5jVmo1T0ZRNTZOeHZjbGpxWitlNVM4TDhtZzFUWkpPS3ZRck4vRkRBSAplSHVNeldEcTlLVURXaU9LN0d3aDFGWHdoVTV2T3BwMTRtZjVCVmp4Y3Qvek9DcHdLd2NYaE5NUVRTTVhYUHFsCllBTjBOKzMzb1pkenRxUEtJWHVjaGp3aFhQOWJCZ2REc0M3MTgzNDlWZFRMblZBN2doQlRCcUJRVFVlWitrVnMKU2xwcENvRUNnWUVBNlRteEJyWXMybDExWmtNUDhyenRtcXhiRlNaU0t0bnh1Rk5LNTlRU3ZPQkVFMmlGUCtxMQpwdHY2elhQWkVaVFBoeUowWU83VFcxQk5mZjJUaVdpNzA1TDFlUTVIVlU3QjVMQkthSkV6RFdPYmt6NWxOWk5GCmxWdnM0UGg3SzJvdjBuNjJkMnZlclpZQzBCOWlpUGlFbHFLaFRialF4QzZJYzM3YWtVQytmb01DZ1lFQXhCaEgKUXJ0ZzlrMHVlejJ6ek5SQ1dXb0Jsa0xwdjhEWU1pUFB5aWZUS0dHZDN5c0hIc05RQVZVTDR1YngzdFkrUjdzeApUS2pRb2dSd2tobTJmQUMvN0VRenZNbXMrYWtEai9wUWVXUDU5VVlOK1ptUUFPbDBtQUx2NnovM0RGMnl6RHI5Ckx4eDBieTJXMERpMGs1N0lER3lIV3ZKUHROcmRBZkY1NlV5VVZJc0NnWUJyNnNNTVBQMnlLUzZxbS90a01hR3MKUVhaLzZkUjVlWkdNM2hXNkFmcU5wU1E2NnRGRml5QjB6ak5XSC9YZ1djQlJZbE1CaTJFSFRyZ2N4Vm9nYWZNSAphbWZsbFFMUzZYZDBqMUpPNG1rQ0dBWWo4dW80Q1NaWWYwbXpxNmFxcHg3cndyQkJ3QXN3dlVvZDdYZlZzMUQrCnRzLzJ1NzcyR0NZUmN6QkZwL1M5YXdLQmdGdXd6b0ZSaElFbWpibHFuSXdHSkJBVEZUTGhqdEx1cFNpc3ZoaFUKanRPdThWYk1rOE82cDhvM3Joc215YW5jbTdxR3VRS1RYUnFrNE00djM3Z1QwYW4wS2d6NGNEMDgza0dRVmRpcworcy9KTmZlajZrWEM0NVhBcWRaaVRtNGwwZGpWTEZXL0JHS0grcURhSXZWenBTN0tBSEJ5SlByMzY2ZGc5aFEwCmpwY0pBb0dBRE50eWMrSlVTSmVhQUd5ZlluUEFkRnBSakZQNUZ6ZGdod1JLNVR2WVI0c2Qwd1lyTXVVNnRPSVQKMHpGMUEwTlRSbmI0SStpUklzU3plZ0xzSHg1OXJKNnY2d3Q3NlIwUEFjWlB6cDVkemxTbXYybGRPNEE5MVRLegp2dEIxRGZHUm5pQ1dpOURjRkJpaVRVZlZUbXRtU3pCRGdsREVQUE51Q0txaGkvamRvQVU9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==`

View File

@@ -0,0 +1,703 @@
package agent_operator
import (
"bufio"
"strings"
"time"
"wdd.io/agent-common/utils"
"wdd.io/agent-operator/image"
)
var CmiiOperator = CmiiK8sOperator{}
// var updateLogPath = "C:\\Users\\wddsh\\Documents\\IdeaProjects\\ProjectOctopus\\cmii_operator\\log\\cmii-update-log.txt"
var updateLogPath = "/home/wdd/IdeaProjects/ProjectOctopus/cmii_operator/log/cmii-update-log.txt"
// FindAppNotHealthyOrRestartCountGreaterThanN 重启次数大于N的所有Deployment
func FindAppNotHealthyOrRestartCountGreaterThanN(cmiiEnv string, restartCount int32) []CmiiDeploymentInterface {
//podInterface := CmiiPodInterface{}
// get all pods
podAll := CmiiOperator.PodAllInterface(cmiiEnv)
// restart map
restartMap := make(map[string]int32, len(podAll))
// restart count
for _, pod := range podAll {
if pod.RestartCount > restartCount {
restart, exists := restartMap[pod.ContainerName]
if exists {
restartMap[pod.ContainerName] = utils.MaxInt32(pod.RestartCount, restart)
} else {
restartMap[pod.ContainerName] = pod.RestartCount
}
}
// unhealthy
if !pod.PodStatus {
restartMap[pod.ContainerName] = pod.RestartCount
}
}
result := make([]CmiiDeploymentInterface, len(restartMap))
index := 0
log.DebugF("[FindAppNotHealthyOrRestartCountGreaterThanN] - restart map is => %v", restartMap)
// find deployment convert to interface
for key, value := range restartMap {
// container Name must equals deployment name
deployment := CmiiOperator.DeploymentOneInterface(cmiiEnv, key)
if deployment != nil {
// deployment exists
log.DebugF("[FindAppNotHealthyOrRestartCountGreaterThanN] - restart [%s] [%s] is [%d]", cmiiEnv, key, value)
result[index] = *deployment
index++
}
}
return result[:index]
}
func FindDeploymentReplicasSmallerThanN(cmiiEnv string, replicasMin int32) (deploymentList []CmiiDeploymentInterface) {
// get all deployments
cmiiDeploymentInterfaces := CmiiOperator.DeploymentAllInterface(cmiiEnv)
cmiiDeploymentInterfaces = FilterAllCmiiAppSoft(cmiiDeploymentInterfaces)
// filter
for _, deploymentInterface := range cmiiDeploymentInterfaces {
if deploymentInterface.Replicas <= replicasMin {
deploymentList = append(deploymentList, deploymentInterface)
}
}
// convert
return deploymentList
}
func FindDeploymentNotHealthy(cmiiEnv string) (deploymentList []CmiiDeploymentInterface) {
// all unhealthy pods
allInterface := CmiiOperator.PodAllInterface(cmiiEnv)
// find the deployments
for _, podInterface := range allInterface {
if !podInterface.PodStatus {
// unhealthy pod
deploymentInterface := CmiiOperator.DeploymentOneInterface(cmiiEnv, podInterface.ContainerName)
if deploymentInterface != nil {
deploymentList = append(deploymentList, *deploymentInterface)
}
}
}
return deploymentList
}
func FindAllNodeNotHealthy() (nodeList []CmiiNodeInterface) {
// dev-cluster
devNodeList := CmiiOperator.NodeAllInterface("dev")
// core-cluster
coreNodeList := CmiiOperator.NodeAllInterface("uat")
// append
coreNodeList = append(coreNodeList, devNodeList...)
// filter
for _, node := range coreNodeList {
if node.Unschedulable {
nodeList = append(nodeList, node)
continue
}
if !node.NodeStatus {
nodeList = append(nodeList, node)
continue
}
if node.MemoryPressure || node.PIDPressure || node.NetworkUnavailable || node.DiskPressure {
nodeList = append(nodeList, node)
continue
}
}
return nodeList
}
func FindPodNotHealthy(cmiiEnv string) (podList []CmiiPodInterface) {
// all unhealthy pods
allInterface := CmiiOperator.PodAllInterface(cmiiEnv)
// find the deployments
for _, podInterface := range allInterface {
if !podInterface.PodStatus {
// unhealthy pod
podList = append(podList, podInterface)
}
}
return podList
}
func GetDeploymentGitInfoFromInnerEnv(cmiiEnv, appName string) (gitBranch, gitCommit string) {
// get app
podList := CmiiOperator.PodByAppName(cmiiEnv, appName)
// get pod
if podList == nil || len(podList) == 0 {
log.ErrorF("[GetDeploymentGitInfoFromInnerEnv] - get app pod error [%s] [%s]", cmiiEnv, appName)
return "", ""
}
// exec env
stdout, stderr := CmiiOperator.PodExec(cmiiEnv, podList[0], []string{"env"})
errLog := stderr.String()
if errLog != "" {
log.ErrorF("[GetDeploymentGitInfoFromInnerEnv] - pod Exec error %s", errLog)
return "", ""
}
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
// Get the current line
line := scanner.Text()
// Check if the current line contains the search term
if strings.HasPrefix(line, "GIT_BRANCH") {
gitBranch = strings.Split(line, "=")[1]
}
if strings.HasPrefix(line, "GIT_COMMIT") {
gitCommit = strings.Split(line, "=")[1]
}
}
// get out git info
return gitBranch, gitCommit
}
func FindCmiiMiddlewarePodInterface(cmiiEnv string) (podList []CmiiPodInterface) {
cmiiPodInterfaces := CmiiOperator.PodAllInterface(cmiiEnv)
for _, podInterface := range cmiiPodInterfaces {
for key := range CmiiMiddlewareNameMap {
if strings.Contains(podInterface.Name, key) {
podList = append(podList, podInterface)
}
}
}
return podList
}
func ScaleCmiiFrontendDeploymentToDesiredReplicas(cmiiEnv string, desiredReplicas int32) (errorUpdateMap map[string]int32) {
frontMap := make(map[string]int32, len(CmiiFrontendAppMap))
for aooName := range CmiiFrontendAppMap {
frontMap[aooName] = desiredReplicas
}
return ScaleDeploymentToDesiredReplicasFromMap(cmiiEnv, frontMap)
}
func ScaleCmiiBackendDeploymentToDesiredReplicas(cmiiEnv string, desiredReplicas int32) (errorUpdateMap map[string]int32) {
backMap := make(map[string]int32, len(CmiiBackendAppMap))
for aooName := range CmiiBackendAppMap {
backMap[aooName] = desiredReplicas
}
return ScaleDeploymentToDesiredReplicasFromMap(cmiiEnv, backMap)
}
func ScaleDeploymentToDesiredReplicasFromMap(cmiiEnv string, nameReplicasMap map[string]int32) map[string]int32 {
errorUpdateMap := make(map[string]int32, len(nameReplicasMap))
// 遍历
for appName, replica := range nameReplicasMap {
exists := CmiiOperator.DeploymentExist(cmiiEnv, appName)
if exists != nil {
scale := CmiiOperator.DeploymentScale(cmiiEnv, appName, replica)
if !scale {
errorUpdateMap[appName] = replica
}
} else {
errorUpdateMap[appName] = replica
}
}
return errorUpdateMap
}
func RestartDeploymentFromList(deploymentList []CmiiDeploymentInterface) bool {
result := true
for _, deployment := range deploymentList {
result = CmiiOperator.DeploymentScale(deployment.Namespace, deployment.Name, 0)
if !result {
return result
}
time.Sleep(time.Second)
result = CmiiOperator.DeploymentScale(deployment.Namespace, deployment.Name, deployment.Replicas)
if !result {
return result
}
}
return result
}
func RestartCmiiBackendDeployment(cmiiEnv string) {
cmiiDeploymentInterfaces := CmiiOperator.DeploymentAllInterface(cmiiEnv)
for _, deploymentInterface := range cmiiDeploymentInterfaces {
if AppNameBelongsToCmiiImage(deploymentInterface.Name) {
if !CmiiOperator.DeploymentRestart(deploymentInterface.Namespace, deploymentInterface.Name) {
log.ErrorF("[RestartCmiiBackendDeployment] - restart of [%s] [%s] failed !", deploymentInterface.Namespace, deploymentInterface.Name)
} else {
log.DebugF("[RestartCmiiBackendDeployment] - restart of [%s] [%s] success !", deploymentInterface.Namespace, deploymentInterface.Name)
}
}
}
log.InfoF("[RestartCmiiBackendDeployment] - restart of all backend app in [%s] success !", CmiiOperator.CurrentNamespace)
}
func RestartCmiiFrontendDeployment(cmiiEnv string) {
cmiiDeploymentInterfaces := CmiiOperator.DeploymentAllInterface(cmiiEnv)
for _, deploymentInterface := range cmiiDeploymentInterfaces {
_, ok := CmiiFrontendAppMap[deploymentInterface.Name]
if ok {
if !CmiiOperator.DeploymentRestart(deploymentInterface.Namespace, deploymentInterface.Name) {
log.ErrorF("[RestartCmiiFrontendDeployment] - restart of [%s] [%s] failed !", deploymentInterface.Namespace, deploymentInterface.Name)
} else {
log.DebugF("[RestartCmiiFrontendDeployment] - restart of [%s] [%s] success !", deploymentInterface.Namespace, deploymentInterface.Name)
}
}
}
log.InfoF("[RestartCmiiFrontendDeployment] - restart of all backend app in [%s] success !", CmiiOperator.CurrentNamespace)
}
func UpdateCmiiDeploymentImageTag(cmiiEnv, appName, newTag string) bool {
cmiiDeploymentInterface := CmiiOperator.DeploymentOneInterface(cmiiEnv, appName)
if cmiiDeploymentInterface == nil {
return false
}
// check if need to update
if cmiiDeploymentInterface.ImageTag == newTag {
log.DebugF("[UpdateCmiiDeploymentImageTag] - [%s] [%s] image tag are the same ! no need to update !", cmiiEnv, appName)
// restart
if CmiiOperator.DeploymentRestart(cmiiEnv, appName) {
return true
} else {
return false
}
}
content := utils.WordSpaceCompletion(utils.TimeSplitFormatString()+" "+cmiiDeploymentInterface.Namespace, 35)
content = utils.WordSpaceCompletion(content+cmiiDeploymentInterface.Name, 75)
content = utils.WordSpaceCompletion(content+cmiiDeploymentInterface.ImageTag, 105)
content = content + newTag + "\n"
log.DebugF("[UpdateCmiiDeploymentImageTag] - prepare to update [%s]!", content)
// update
tag := CmiiOperator.DeploymentUpdateTag(cmiiDeploymentInterface.Namespace, cmiiDeploymentInterface.Name, newTag)
if !tag {
log.ErrorF("[UpdateCmiiDeploymentImageTag] - [%s] update failed !", content)
return false
}
// append log
utils.AppendContentToFile(content, updateLogPath)
// re-get from env
time.Sleep(time.Second)
deploy := CmiiOperator.DeploymentOneInterface(cmiiEnv, appName)
if deploy == nil {
log.ErrorF("[UpdateCmiiDeploymentImageTag] - unknown error happened ! [%s] [%s] not exists !", cmiiEnv, appName)
return false
}
// log
//log.InfoF("[UpdateCmiiDeploymentImageTag] - real image tag are [%s] update tag [%s] success ! ", deploy.Image, content)
return true
}
func UpdateCmiiImageTagFromNameTagMap(cmiiEnv string, nameTagMap map[string]string) (result map[string]string) {
result = make(map[string]string, len(nameTagMap))
for appName, newTag := range nameTagMap {
if AppNameBelongsToCmiiImage(appName) {
if UpdateCmiiDeploymentImageTag(cmiiEnv, appName, newTag) {
log.InfoF("[UpdateCmiiImageTagFromNameTagMap] - %s %s to %s", cmiiEnv, appName, newTag)
result[appName] = newTag
} else {
result[appName] = "false"
}
}
}
return result
}
func RollBackCmiiDeploymentFromUpdateLog(updateLog string) bool {
//if !executor.BasicFindContentInFile(updateLog, updateLogPath) {
// log.ErrorF("[RollBackCmiiDeploymentFromUpdateLog] - [%s] no this update log ! use update instead ! => ", updateLog)
// return false
//}
split := strings.Split(updateLog, " ")
index := 0
cmiiEnv := ""
appName := ""
fromTag := ""
newTag := ""
for _, s := range split {
if s != "" {
if index == 1 {
cmiiEnv = s
} else if index == 2 {
appName = s
} else if index == 3 {
fromTag = s
} else if index == 4 {
newTag = s
}
index++
}
}
log.InfoF("[RollBackCmiiDeploymentFromUpdateLog] - rollback [%s] [%s] from [%s] to [%s]", cmiiEnv, appName, newTag, fromTag)
rollback := UpdateCmiiDeploymentImageTag(cmiiEnv, appName, fromTag)
return rollback
}
// BackupAllDeploymentFromEnv 从DEMO提取全部的CMII的应用
func BackupAllDeploymentFromEnv(cmiiEnv string) bool {
allInterface := CmiiOperator.DeploymentAllInterface(cmiiEnv)
// must filter
allInterface = FilterAllCmiiAppSoft(allInterface)
filePath := "C:\\Users\\wddsh\\Documents\\IdeaProjects\\ProjectOctopus\\cmii_operator\\log\\all-" + CmiiOperator.CurrentNamespace + "-" + utils.TimeSplitFormatString() + ".txt"
log.InfoF("[BackupAllDeploymentFromEnv] - backup all image from %s => %s", CmiiOperator.CurrentNamespace, filePath)
firstCol := 0
secondCol := 0
thirdCol := 0
fourthCol := 0
for _, deploymentInterface := range allInterface {
firstCol = utils.MaxInt(len(deploymentInterface.Name), firstCol)
secondCol = utils.MaxInt(len(deploymentInterface.ImageTag), secondCol)
thirdCol = utils.MaxInt(len(deploymentInterface.GitBranch), thirdCol)
fourthCol = utils.MaxInt(len(deploymentInterface.GitCommit), fourthCol)
}
firstCol += 2
secondCol += 2
secondCol += firstCol
thirdCol += 2
thirdCol += secondCol
fourthCol += 2
fourthCol += thirdCol
for _, deploymentInterface := range allInterface {
if deploymentInterface.GitBranch == "" {
branch, commit := GetDeploymentGitInfoFromInnerEnv(deploymentInterface.Namespace, deploymentInterface.Name)
deploymentInterface.GitBranch = branch
deploymentInterface.GitCommit = commit
}
content := utils.WordSpaceCompletion(deploymentInterface.Name, firstCol)
content = utils.WordSpaceCompletion(content+deploymentInterface.ImageTag, secondCol)
content = utils.WordSpaceCompletion(content+deploymentInterface.GitBranch, thirdCol)
content = utils.WordSpaceCompletion(content+deploymentInterface.GitCommit, fourthCol)
content += "\n"
if !utils.AppendContentToFile(content, filePath) {
log.ErrorF("[BackupAllDeploymentFromEnv] - write to file %s error with contend %s", filePath, content)
return false
}
}
return true
}
func BackupAllCmiiDeploymentToMap(cmiiEnv string) (backendMap, frontendMap, srsMap map[string]string) {
allInterface := CmiiOperator.DeploymentAllInterface(cmiiEnv)
allInterface = FilterAllCmiiAppSoft(allInterface)
backendMap = make(map[string]string, len(allInterface))
frontendMap = make(map[string]string, len(allInterface))
srsMap = make(map[string]string, len(allInterface))
for _, deploymentInterface := range allInterface {
if strings.Contains(deploymentInterface.Name, "platform") {
frontendMap[deploymentInterface.Name] = deploymentInterface.ImageTag
} else {
backendMap[deploymentInterface.Name] = deploymentInterface.ImageTag
}
}
// add srs part
for key, value := range CmiiSrsAppMap {
var app *CmiiDeploymentInterface
if strings.Contains(value, "deployment") {
app = CmiiOperator.DeploymentOneInterface(cmiiEnv, key)
if app != nil {
for _, imageName := range app.ContainerImageMap {
split := strings.Split(imageName, ":")
if strings.Contains(split[0], image.CmiiHarborPrefix) {
split[0] = strings.Split(split[0], image.CmiiHarborPrefix)[1]
}
srsMap[split[0]] = split[1]
}
}
} else if strings.Contains(value, "state") {
app = CmiiOperator.StatefulSetOneInterface(cmiiEnv, key)
if app != nil {
for _, imageName := range app.ContainerImageMap {
split := strings.Split(imageName, ":")
split[0], _ = strings.CutPrefix(split[0], image.CmiiHarborPrefix)
srsMap[split[0]] = split[1]
}
}
}
}
return backendMap, frontendMap, srsMap
}
func BackUpAllCmiiAppImageNameFromEnv(cmiiEnv string) {
CmiiOperator.changeOperatorEnv(cmiiEnv)
filePath := "C:\\Users\\wddsh\\Documents\\IdeaProjects\\ProjectOctopus\\cmii_operator\\log\\images-" + CmiiOperator.CurrentNamespace + "-" + utils.TimeSplitFormatString() + ".txt"
only := make(map[string]string, 150)
// front
utils.AppendContentToFile("---\n", filePath)
for key, value := range CmiiFrontendAppMap {
_, ok := only[key]
if !ok {
deploy := CmiiOperator.DeploymentOneInterface(cmiiEnv, key)
if deploy != nil {
only[key] = value
utils.AppendContentToFile(deploy.Image+"\n", filePath)
}
}
}
utils.AppendContentToFile("---\n", filePath)
for key, value := range CmiiBackendAppMap {
_, ok := only[key]
if !ok {
deploy := CmiiOperator.DeploymentOneInterface(cmiiEnv, key)
if deploy != nil {
only[key] = value
utils.AppendContentToFile(deploy.Image+"\n", filePath)
}
}
}
// backend
utils.AppendContentToFile("---\n", filePath)
// gis server
for key, value := range CmiiGISAppMap {
_, ok := only[key]
if !ok {
deploy := CmiiOperator.DeploymentOneInterface(cmiiEnv, key)
if deploy != nil {
only[key] = value
utils.AppendContentToFile(deploy.Image+"\n", filePath)
}
}
}
// srs
utils.AppendContentToFile("---\n", filePath)
for key, value := range CmiiSrsAppMap {
_, ok := only[key]
if !ok {
var app *CmiiDeploymentInterface
if strings.Contains(value, "deployment") {
app = CmiiOperator.DeploymentOneInterface(cmiiEnv, key)
if app != nil {
only[key] = value
utils.AppendContentToFile(app.Image+"\n", filePath)
}
} else if strings.Contains(value, "state") {
app = CmiiOperator.StatefulSetOneInterface(cmiiEnv, key)
if app != nil {
only[key] = value
for _, imageName := range app.ContainerImageMap {
utils.AppendContentToFile(imageName+"\n", filePath)
}
}
}
}
}
utils.AppendContentToFile("---\n", filePath)
}
func FilterAllCmiiAppStrict(source []CmiiDeploymentInterface) (result []CmiiDeploymentInterface) {
for _, c := range source {
_, ok := CmiiBackendAppMap[c.ContainerName]
if !ok {
_, ok = CmiiFrontendAppMap[c.ContainerName]
if !ok {
log.WarnF("[FilterAllCmiiAppStrict] - [%s] not cmii pod ", c.ContainerName)
continue
}
}
result = append(result, c)
}
return result
}
func FilterAllCmiiAppSoft(source []CmiiDeploymentInterface) (result []CmiiDeploymentInterface) {
for _, c := range source {
if strings.Contains(c.ContainerName, "redis") {
continue
}
if strings.Contains(c.ContainerName, "emqxs") {
continue
}
if strings.Contains(c.ContainerName, "rabbitmq") {
continue
}
if strings.Contains(c.ContainerName, "nacos") {
continue
}
if strings.Contains(c.ContainerName, "oss") {
continue
}
if strings.Contains(c.ContainerName, "minio") {
continue
}
if strings.HasPrefix(c.ContainerName, "nfs") {
continue
}
if strings.HasPrefix(c.ContainerName, "operator") {
continue
}
if strings.HasPrefix(c.ContainerName, "proxy") {
continue
}
result = append(result, c)
}
return result
}
func FilterAllCmiiPodStrict(podList []CmiiPodInterface) (result []CmiiPodInterface) {
for _, c := range podList {
_, ok := CmiiBackendAppMap[c.ContainerName]
if !ok {
_, ok = CmiiFrontendAppMap[c.ContainerName]
if !ok {
log.WarnF("[FilterAllCmiiPodStrict] - [%s] not cmii pod ", c.ContainerName)
continue
}
}
result = append(result, c)
}
return result
}
func FilterAllCmiiPodSoft(podList []CmiiPodInterface) (result []CmiiPodInterface) {
for _, c := range podList {
if strings.Contains(c.ContainerName, "redis") {
continue
}
if strings.Contains(c.ContainerName, "emqxs") {
continue
}
if strings.Contains(c.ContainerName, "rabbitmq") {
continue
}
if strings.Contains(c.ContainerName, "nacos") {
continue
}
if strings.Contains(c.ContainerName, "oss") {
continue
}
if strings.Contains(c.ContainerName, "minio") {
continue
}
if strings.HasPrefix(c.ContainerName, "nfs") {
continue
}
if strings.HasPrefix(c.ContainerName, "operator") {
continue
}
if strings.HasPrefix(c.ContainerName, "proxy") {
continue
}
if strings.HasPrefix(c.ContainerName, "cleanlog") {
continue
}
result = append(result, c)
}
return result
}
func FilterAllCmiiNodeSoft(nodeList []CmiiNodeInterface) (result []CmiiNodeInterface) {
for _, nodeInterface := range nodeList {
if strings.HasPrefix(nodeInterface.Name, "ai") {
continue
}
if strings.HasPrefix(nodeInterface.Name, "35") {
continue
}
result = append(result, nodeInterface)
}
return result
}
func AppNameBelongsToCmiiImage(appName string) bool {
_, ok := CmiiBackendAppMap[appName]
if !ok {
_, ok = CmiiFrontendAppMap[appName]
if !ok {
log.WarnF("[AppNameBelongsToCmiiImage] - [%s] not cmii app ", appName)
return false
} else {
return true
}
} else {
return true
}
}

View File

@@ -0,0 +1,260 @@
package agent_operator
import (
"fmt"
"testing"
"time"
"wdd.io/agent-common/assert"
"wdd.io/agent-common/message_pusher"
"wdd.io/agent-common/utils"
)
var CmiiDevNamespaceList = []string{
"uavcloud-dev",
"uavcloud-devflight",
"uavcloud-devoperation",
}
func TestFindAppNotHealthyOrRestartCountGreaterThanN(t *testing.T) {
deploymentRestartCountGreaterThanN := FindAppNotHealthyOrRestartCountGreaterThanN("devflight", 10)
deploymentRestartCountGreaterThanN = FilterAllCmiiAppSoft(deploymentRestartCountGreaterThanN)
for _, deploymentInterface := range deploymentRestartCountGreaterThanN {
println()
utils.BeautifulPrint(deploymentInterface)
println()
}
}
func TestFindDeploymentReplicasSmallerThanN(t *testing.T) {
deploymentReplicasSmallerThanN := FindDeploymentReplicasSmallerThanN("devflight", 0)
for _, deploymentInterface := range deploymentReplicasSmallerThanN {
println()
utils.BeautifulPrint(deploymentInterface)
println()
}
}
func TestFindCmiiMiddlewarePodInterface(t *testing.T) {
middlewarePodInterface := FindCmiiMiddlewarePodInterface(integration)
for _, middlePod := range middlewarePodInterface {
println()
utils.BeautifulPrint(middlePod)
println()
}
}
func TestRollBackCmiiDeploymentFromUpdateLog(t *testing.T) {
updateLog := RollBackCmiiDeploymentFromUpdateLog("2024-01-10-14-37-07 uavcloud-devflight cmii-uav-depotautoreturn 12345678 123sdsa45678")
assert.Equal(t, updateLog, true, "roll back from update log failed !")
}
func TestRestartCmiiBackendDeployment(t *testing.T) {
RestartCmiiBackendDeployment("dev")
}
func TestRestartCmiiFrontendDeployment(t *testing.T) {
RestartCmiiFrontendDeployment("dev")
}
func TestFindDeploymentNotHealthy(t *testing.T) {
for _, devNamespace := range CmiiDevNamespaceList {
notHealthy := FindDeploymentNotHealthy(devNamespace)
notHealthy = FilterAllCmiiAppSoft(notHealthy)
for _, deploymentInterface := range notHealthy {
utils.BeautifulPrint(deploymentInterface)
}
}
}
func TestFindAllNodeNotHealthy(t *testing.T) {
start := time.Now()
allNodeNotHealthy := FindAllNodeNotHealthy()
elapsed := time.Since(start).Milliseconds()
fmt.Printf("执行耗时: %d ms\n", elapsed)
allNodeNotHealthy = FilterAllCmiiNodeSoft(allNodeNotHealthy)
assert.Equal(t, len(allNodeNotHealthy), 0, "have unhealthy pod !")
for _, nodeInterface := range allNodeNotHealthy {
println()
utils.BeautifulPrint(nodeInterface)
println()
}
}
func TestFindPodNotHealthy(t *testing.T) {
podNotHealthy := FindPodNotHealthy("devfl")
podNotHealthy = FilterAllCmiiPodSoft(podNotHealthy)
for _, podInterface := range podNotHealthy {
t.Logf("[%s] [%s]", podInterface.Name, podInterface.PodPhase)
}
}
func TestFindPodNotHealthy_And_Delete(t *testing.T) {
podNotHealthy := FindPodNotHealthy("devf")
podNotHealthy = FilterAllCmiiPodSoft(podNotHealthy)
for _, podInterface := range podNotHealthy {
t.Logf("[%s] [%s]", podInterface.Name, podInterface.PodPhase)
podDelete := CmiiOperator.PodDelete(podInterface.Namespace, podInterface.Name)
assert.Equal(t, podDelete, true, "delete of ", podInterface.Namespace, podInterface.Name, " failed !")
}
}
func TestFilterAllCmiiAppStrict(t *testing.T) {
allInterface := CmiiOperator.DeploymentAllInterface("devflight")
FilterAllCmiiAppStrict(allInterface)
}
func TestRestartDeploymentFromList(t *testing.T) {
allInterface := CmiiOperator.DeploymentAllInterface("devflight")
allInterface = FilterAllCmiiAppSoft(allInterface)
RestartDeploymentFromList(allInterface)
}
func TestBackupAllCmiiDeploymentToMap(t *testing.T) {
backendMap, frontendMap, srsMap := BackupAllCmiiDeploymentToMap(demo)
utils.BeautifulPrint(backendMap)
utils.BeautifulPrint(frontendMap)
utils.BeautifulPrint(srsMap)
}
func TestUpdateCmiiImageTagFromNameTagMap(t *testing.T) {
cmii530BackendMap := map[string]string{
"cmii-admin-data": "5.3.0",
"cmii-admin-gateway": "5.3.0",
"cmii-admin-user": "5.3.0",
"cmii-open-gateway": "5.3.0",
"cmii-suav-supervision": "5.3.0",
"cmii-uav-airspace": "5.3.0",
"cmii-uav-alarm": "5.3.0",
"cmii-uav-brain": "5.3.0",
"cmii-uav-cloud-live": "5.3.0",
"cmii-uav-cms": "5.3.0",
"cmii-uav-data-post-process": "5.3.0",
"cmii-uav-developer": "5.3.0",
"cmii-uav-device": "5.3.0",
"cmii-uav-emergency": "5.3.0",
"cmii-uav-gateway": "5.3.0",
"cmii-uav-gis-server": "5.3.0",
"cmii-uav-industrial-portfolio": "5.3.0",
"cmii-uav-integration": "5.3.0",
"cmii-uav-logger": "5.3.0",
"cmii-uav-material-warehouse": "5.3.0",
"cmii-uav-mission": "5.3.0",
"cmii-uav-mqtthandler": "5.3.0",
"cmii-uav-notice": "5.3.0",
"cmii-uav-oauth": "5.3.0",
"cmii-uav-process": "5.3.0",
"cmii-uav-surveillance": "5.3.0",
"cmii-uav-threedsimulation": "5.3.0",
"cmii-uav-tower": "5.3.0",
"cmii-uav-user": "5.3.0",
"cmii-uav-waypoint": "5.3.0",
//"cmii-uav-grid-datasource": "5.2.0-24810",
//"cmii-uav-grid-engine": "5.1.0",
//"cmii-uav-grid-manage": "5.1.0",
}
cmii530FrontendMap := map[string]string{
"cmii-suav-platform-supervision": "5.3.0",
"cmii-suav-platform-supervisionh5": "5.3.0",
"cmii-uav-platform": "5.3.0",
"cmii-uav-platform-ai-brain": "5.3.0",
"cmii-uav-platform-armypeople": "5.3.0",
"cmii-uav-platform-base": "5.3.0",
"cmii-uav-platform-cms-portal": "5.3.0",
"cmii-uav-platform-detection": "5.3.0",
"cmii-uav-platform-emergency-rescue": "5.3.0",
"cmii-uav-platform-logistics": "5.3.0",
"cmii-uav-platform-media": "5.3.0",
"cmii-uav-platform-multiterminal": "5.3.0",
"cmii-uav-platform-mws": "5.3.0",
"cmii-uav-platform-oms": "5.3.0",
"cmii-uav-platform-open": "5.3.0",
"cmii-uav-platform-securityh5": "5.3.0",
"cmii-uav-platform-seniclive": "5.3.0",
"cmii-uav-platform-share": "5.3.0",
"cmii-uav-platform-splice": "5.3.0",
"cmii-uav-platform-threedsimulation": "5.3.0",
"cmii-uav-platform-visualization": "5.3.0",
//"cmii-uav-platform-security": "4.1.6",
}
result := UpdateCmiiImageTagFromNameTagMap("demo", cmii530BackendMap)
utils.BeautifulPrint(result)
result = UpdateCmiiImageTagFromNameTagMap("demo", cmii530FrontendMap)
utils.BeautifulPrint(result)
}
func TestScaleCmiiFrontendDeploymentToDesiredReplicas(t *testing.T) {
ScaleCmiiFrontendDeploymentToDesiredReplicas(dev, 0)
}
func TestScaleCmiiBackendDeploymentToDesiredReplicas(t *testing.T) {
ScaleCmiiBackendDeploymentToDesiredReplicas(dev, 0)
}
func TestBackupAllDeploymentFromEnv(t *testing.T) {
BackupAllDeploymentFromEnv(demo)
}
func TestBackUpAllCmiiAppImageNameFromEnv(t *testing.T) {
BackUpAllCmiiAppImageNameFromEnv(demo)
}
func TestRestartCmiiDeployment(t *testing.T) {
cmiiEnv := integration
appName := "cmii-uav-device"
kill := CmiiOperator.DeploymentRestartByKill(cmiiEnv, appName)
assert.Equal(t, kill, true, "have unhealthy pod !")
check := CmiiOperator.DeploymentStatusCheck(cmiiEnv, appName, 180)
assert.Equal(t, check, true, "DeploymentStatusCheck failed !")
}
func TestUpdateCmiiDeploymentImageTag(t *testing.T) {
cmiiEnv := demo
appName := "cmii-uav-platform"
newTag := "5.4.0-031901"
tag := UpdateCmiiDeploymentImageTag(cmiiEnv, appName, newTag)
assert.Equal(t, tag, true, "update image tag failed !")
utils.SplitLinePrint()
check := CmiiOperator.DeploymentStatusCheck(cmiiEnv, appName, 300)
assert.Equal(t, check, true, "deployment run failed!")
// push message
message_pusher.PushCmiiUpdateMessage(cmiiEnv, appName, newTag, check)
}

View File

@@ -0,0 +1,85 @@
package agent_operator
import (
"github.com/minio/minio-go"
"os"
"strings"
)
type CmiiMinioOperator struct {
LocalEndpoint string
PublicEndpoint string
AccessKeyID string
SecretAccessKey string
LocalClient *minio.Client
PublicClient *minio.Client
OctopusBucketName string
}
const (
DefaultLocalEndpoint = "http://10.250.0.100:9000"
DefaultPublicEndpoint = "http://42.192.52.227:9000"
DefaultAccessKeyID = "cmii"
DefaultSecretAccessKey = "B#923fC7mk"
DefaultOctopusBucketName = "octopus"
)
func (op CmiiMinioOperator) buildCmiiMinioOperator() {
var err error
if op.LocalClient == nil {
// 初始化Minio客户端对象。
op.LocalClient, err = minio.New(DefaultLocalEndpoint, DefaultAccessKeyID, DefaultSecretAccessKey, false)
if err != nil {
log.ErrorF("[buildCmiiMinioOperator] - build for LocalClient error !=> %s", err.Error())
}
}
if op.PublicClient == nil {
// 初始化Minio客户端对象。
op.PublicClient, err = minio.New(DefaultPublicEndpoint, DefaultAccessKeyID, DefaultSecretAccessKey, false)
if err != nil {
log.ErrorF("[buildCmiiMinioOperator] - build for PublicClient error ! => %s", err.Error())
}
}
log.DebugF("[buildCmiiMinioOperator] - build client success !")
}
func (op CmiiMinioOperator) UploadToLocalOctopus(filePath, fileName string) bool {
op.buildCmiiMinioOperator()
return op.uploadToOctopus(op.LocalClient, filePath, fileName)
}
func (op CmiiMinioOperator) UploadToPublicOctopus(filePath, fileName string) bool {
op.buildCmiiMinioOperator()
return op.uploadToOctopus(op.PublicClient, filePath, fileName)
}
func (op CmiiMinioOperator) uploadToOctopus(client *minio.Client, filePath, fileName string) bool {
if !strings.HasSuffix(filePath, "/") {
filePath += "/"
}
// 打开要上传的文件
file, err := os.Open(filePath + fileName)
if err != nil {
log.ErrorF("[uploadToOctopus] - file %s open error! %s", filePath+fileName, err.Error())
}
defer file.Close()
// 使用PutObject上传文件
n, err := client.PutObject(DefaultOctopusBucketName, fileName, file, -1, minio.PutObjectOptions{})
if err != nil {
log.ErrorF("[uploadToOctopus] - upload %s error %s", filePath+fileName, err.Error())
return false
}
log.InfoF("[uploadToOctopus] - uploaded %s of size %d", filePath+fileName, n)
return true
}

View File

@@ -0,0 +1 @@
package agent_operator

View File

@@ -0,0 +1,312 @@
package agent_operator
import (
"errors"
"io/fs"
"os"
"path/filepath"
"slices"
"strings"
"wdd.io/agent-common/utils"
"wdd.io/agent-operator/image"
)
const OfflineImageGzipFolderPrefix = "/root/octopus_image/"
const OfflineDeployHarborHost = "harbor.wdd.io"
const PublicDeployHarborHost = "42.192.52.227"
const DirectPushDeployHarborHost = "36.134.71.138"
type ImageSyncEntity struct {
ProjectName string
ProjectVersion string
DirectHarborHost string
PushToDemoMinio bool
}
type ImageSyncResult struct {
ErrorPullImageList []string
ErrorGzipImageList []string
ErrorPushImageNameList []string
RealImageNameList []string
RealGzipFileNameList []string
AllCmiiImageNameList []string
}
func (sync ImageSyncEntity) PullFromEntityAndSyncConditionally() (imageSyncResult ImageSyncResult) {
var realCmiiImageList []string
var errorPullImageList []string
var errorGzipImageList []string
var allCmiiImageNameList []string
var allGzipFileNameList []string
var errorPushImageNameList []string
var gzipFolderFullPath string
// get all image name by Name or Version
// pull images
// compress
if sync.ProjectVersion != "" {
// get version
if sync.DirectHarborHost == "" {
errorPullImageList, errorGzipImageList, allCmiiImageNameList = FetchVersionImages(sync.ProjectVersion, true)
gzipFolderFullPath = OfflineImageGzipFolderPrefix + sync.ProjectVersion
} else {
errorPullImageList, errorGzipImageList, allCmiiImageNameList = FetchVersionImages(sync.ProjectVersion, false)
}
} else {
// get demo images
if sync.DirectHarborHost == "" {
errorPullImageList, errorGzipImageList, allCmiiImageNameList = FetchDemoImages(sync.ProjectName, true)
gzipFolderFullPath = OfflineImageGzipFolderPrefix + sync.ProjectName
} else {
errorPullImageList, errorGzipImageList, allCmiiImageNameList = FetchDemoImages(sync.ProjectName, false)
}
}
backAllImageNameList := allCmiiImageNameList[:]
realCmiiImageList = slices.DeleteFunc(backAllImageNameList, func(imageName string) bool {
return slices.Contains(errorPullImageList, imageName)
})
realCmiiImageList = slices.DeleteFunc(backAllImageNameList, func(imageName string) bool {
return slices.Contains(errorGzipImageList, imageName)
})
// direct push if can
if sync.DirectHarborHost != "" {
// push to
errorPushImageNameList = image.TagFromListAndPushToCHarbor(realCmiiImageList, sync.DirectHarborHost)
// build
imageSyncResult.AllCmiiImageNameList = allCmiiImageNameList
imageSyncResult.ErrorPullImageList = errorPullImageList
imageSyncResult.ErrorGzipImageList = errorGzipImageList
imageSyncResult.ErrorPushImageNameList = errorPushImageNameList
imageSyncResult.RealImageNameList = realCmiiImageList
// no gzip file
return imageSyncResult
}
// get gzip file name list
err := filepath.WalkDir(gzipFolderFullPath, func(path string, d fs.DirEntry, err error) error {
if err != nil {
log.ErrorF("error getting gzip file name list 1! %s", err.Error())
}
if !d.IsDir() {
allGzipFileNameList = append(allGzipFileNameList, d.Name())
}
return nil
})
if err != nil {
log.ErrorF("error getting gzip file name list 2! %s", err.Error())
}
// push to demo minio
if sync.PushToDemoMinio {
log.InfoF("pretend to push to minio !")
// create path
// push
}
// build
imageSyncResult.AllCmiiImageNameList = allCmiiImageNameList
imageSyncResult.ErrorPullImageList = errorPullImageList
imageSyncResult.ErrorGzipImageList = errorGzipImageList
imageSyncResult.ErrorPushImageNameList = errorPushImageNameList
imageSyncResult.RealGzipFileNameList = allGzipFileNameList
imageSyncResult.RealImageNameList = realCmiiImageList
// no gzip file
return imageSyncResult
}
func remove(s1, s2 []string) []string {
m := make(map[string]struct{}, len(s2))
for _, v := range s2 {
m[v] = struct{}{}
}
res := make([]string, 0, len(s1))
for _, v := range s1 {
if _, ok := m[v]; !ok {
res = append(res, v)
}
}
return res
}
func FetchDemoImages(projectName string, gzipSplit bool) (errorPullImageList, errorGzipImageList, allCmiiImageName []string) {
// generate a project folder
err := os.MkdirAll(OfflineImageGzipFolderPrefix+projectName, os.ModeDir)
if err != nil {
if !errors.Is(err, os.ErrExist) {
log.ErrorF("[FetchDemoImages] - create folder of %s error %s", OfflineImageGzipFolderPrefix+projectName, err.Error())
return errorPullImageList, errorGzipImageList, allCmiiImageName
}
}
// get demo image version map
backendMap, frontendMap, srsMap := BackupAllCmiiDeploymentToMap(demo)
utils.BeautifulPrint(backendMap)
utils.BeautifulPrint(frontendMap)
utils.BeautifulPrint(srsMap)
// save map to file
backendMapFile := OfflineImageGzipFolderPrefix + projectName + "-backend-app.json"
frontendMapFile := OfflineImageGzipFolderPrefix + projectName + "-frontend-app.json"
srsMapFile := OfflineImageGzipFolderPrefix + projectName + "-srs-app.json"
_ = os.Remove(backendMapFile)
_ = os.Remove(frontendMapFile)
_ = os.Remove(srsMapFile)
utils.AppendContentToFile(
utils.BeautifulPrintToString(backendMap),
backendMapFile,
)
utils.AppendContentToFile(
utils.BeautifulPrintToString(frontendMap),
frontendMapFile,
)
utils.AppendContentToFile(
utils.BeautifulPrintToString(srsMapFile),
srsMapFile,
)
// download image
backendFullNameList, backendPull := image.PullFromCmiiHarborByMap(backendMap, true)
frontendFullNameList, frontendPull := image.PullFromCmiiHarborByMap(frontendMap, true)
srsFullNameList, srsPull := image.PullFromCmiiHarborByMap(srsMap, true)
allCmiiImageName = append(allCmiiImageName, backendFullNameList...)
allCmiiImageName = append(allCmiiImageName, frontendFullNameList...)
allCmiiImageName = append(allCmiiImageName, srsFullNameList...)
// compress image
if gzipSplit {
for image_name, tag := range backendMap {
if !image.SaveToTarGZ(image_name+":"+tag, OfflineImageGzipFolderPrefix+projectName+"/app/") {
errorGzipImageList = append(errorGzipImageList, image.CmiiHarborPrefix+image_name+":"+tag)
}
}
for image_name, tag := range frontendMap {
if !image.SaveToTarGZ(image_name+":"+tag, OfflineImageGzipFolderPrefix+projectName+"/app/") {
errorGzipImageList = append(errorGzipImageList, image.CmiiHarborPrefix+image_name+":"+tag)
}
}
for image_name, tag := range srsMap {
if !image.SaveToTarGZ(image_name+":"+tag, OfflineImageGzipFolderPrefix+projectName+"/app/") {
errorGzipImageList = append(errorGzipImageList, image.CmiiHarborPrefix+image_name+":"+tag)
}
}
}
// upload to harbor
// clean up images
errorPullImageList = append(errorPullImageList, backendPull...)
errorPullImageList = append(errorPullImageList, frontendPull...)
errorPullImageList = append(errorPullImageList, srsPull...)
return errorPullImageList, errorGzipImageList, allCmiiImageName
}
func FetchVersionImages(cmiiVersion string, shouldGzip bool) (errorPullImageList, errorGzipImageList, allCmiiImageName []string) {
// generate a project folder
err := os.MkdirAll(OfflineImageGzipFolderPrefix+cmiiVersion, os.ModeDir)
if err != nil {
if !errors.Is(err, os.ErrExist) {
log.ErrorF("[FetchDemoImages] - create folder of %s error %s", OfflineImageGzipFolderPrefix+cmiiVersion, err.Error())
return errorPullImageList, errorGzipImageList, allCmiiImageName
}
}
backendMap := CmiiBackendAppMap
frontendMap := CmiiFrontendAppMap
for app := range backendMap {
backendMap[app] = cmiiVersion
}
for app := range frontendMap {
frontendMap[app] = cmiiVersion
}
allCmiiImageName = append(allCmiiImageName, image.ConvertCMiiImageMapToList(backendMap)...)
allCmiiImageName = append(allCmiiImageName, image.ConvertCMiiImageMapToList(frontendMap)...)
for key, value := range CmiiSrsAppMap {
var app *CmiiDeploymentInterface
if strings.Contains(value, "deployment") {
app = CmiiOperator.DeploymentOneInterface(demo, key)
if app != nil {
allCmiiImageName = append(allCmiiImageName, app.Image)
}
} else if strings.Contains(value, "state") {
app = CmiiOperator.StatefulSetOneInterface(demo, key)
if app != nil {
for _, imageName := range app.ContainerImageMap {
allCmiiImageName = append(allCmiiImageName, imageName)
}
}
}
}
utils.BeautifulPrintListWithTitle(allCmiiImageName, "Cmii Version Image => "+cmiiVersion)
// do work
if shouldGzip {
errorPullImageList, errorGzipImageList = image.PullFromListAndCompressSplit(allCmiiImageName, OfflineImageGzipFolderPrefix+cmiiVersion)
} else {
errorPullImageList = image.PullFromFullNameList(allCmiiImageName)
}
return errorPullImageList, errorGzipImageList, allCmiiImageName
}
func FetchDependencyRepos(gzipSplit bool) (errorPullImageList, errorGzipImageList []string) {
err := os.MkdirAll(OfflineImageGzipFolderPrefix, os.ModeDir)
if err != nil {
if !errors.Is(err, os.ErrExist) {
log.ErrorF("[FetchDependencyRepos] - create folder of %s error %s", OfflineImageGzipFolderPrefix, err.Error())
}
}
errorPullImageList, errorGzipImageList = image.PullFromListAndCompressSplit(image.MiddlewareAmd64, OfflineImageGzipFolderPrefix+"middle/")
pull, gzipImageList := image.PullFromListAndCompressSplit(image.Rancher1204Amd64, OfflineImageGzipFolderPrefix+"rke/")
return append(errorPullImageList, pull...), append(errorGzipImageList, gzipImageList...)
}
func LoadSplitCmiiGzipImageToTargetHarbor(projectName, targetHarborHost string) (errorLoadImageNameList, errorPushImageNameList []string) {
// list folder
projectGzipFolder := OfflineImageGzipFolderPrefix + projectName
errorLoadImageNameList = append(errorLoadImageNameList, image.LoadFromFolderPath(projectGzipFolder)...)
// read from json
errorPushImageNameList = append(errorPushImageNameList, image.TagFromListAndPushToCHarbor(image.Cmii520DemoImageList, targetHarborHost)...)
// re-tag
// push
// todo clean host and harbor
// check harbor exits
return errorLoadImageNameList, errorPushImageNameList
}
func LoadSplitDepGzipImageToTargetHarbor(targetHarborHost string) (errorLoadImageNameList []string, errorPushImageNameList []string) {
//middle := OfflineImageGzipFolderPrefix + "middle/"
//rke := OfflineImageGzipFolderPrefix + "rke/"
//errorLoadImageNameList = append(errorLoadImageNameList, ImageLoadFromFolderPath(middle)...)
//errorLoadImageNameList = append(errorLoadImageNameList, ImageLoadFromFolderPath(rke)...)
errorPushImageNameList = append(errorPushImageNameList, image.TagFromListAndPushToCHarbor(image.MiddlewareAmd64, targetHarborHost)...)
errorPushImageNameList = append(errorPushImageNameList, image.TagFromListAndPushToCHarbor(image.Rancher1204Amd64, targetHarborHost)...)
return errorLoadImageNameList, errorPushImageNameList
}

View File

@@ -0,0 +1,57 @@
package agent_operator
import (
"testing"
"wdd.io/agent-common/utils"
)
func TestFetchDemoImages(t *testing.T) {
errorPullImageList, errorGzipImageList, allCmiiImageName := FetchDemoImages("shls", true)
utils.BeautifulPrintListWithTitle(errorPullImageList, "cmii errorPullImageList")
utils.BeautifulPrintListWithTitle(errorGzipImageList, "cmii errorGzipImageList")
utils.BeautifulPrintListWithTitle(allCmiiImageName, "cmii allCmiiImageName")
}
func TestFetchVersionImages(t *testing.T) {
errorPullImageList, errorGzipImageList, allCmiiImageName := FetchVersionImages("5.4.0", true)
utils.BeautifulPrintListWithTitle(errorPullImageList, "cmii errorPullImageList")
utils.BeautifulPrintListWithTitle(errorGzipImageList, "cmii errorGzipImageList")
utils.BeautifulPrintListWithTitle(allCmiiImageName, "cmii allCmiiImageName")
}
func TestFetchDependencyRepos(t *testing.T) {
errorPullImageList, errorGzipImageList := FetchDependencyRepos(true)
utils.BeautifulPrintListWithTitle(errorPullImageList, "dep errorPullImageList")
utils.BeautifulPrintListWithTitle(errorGzipImageList, "dep errorGzipImageList")
}
func TestLoadSplitGzipImageToTargetHarbor(t *testing.T) {
errorLoadImageNameList, errorPushImageNameList := LoadSplitCmiiGzipImageToTargetHarbor("xmyd", DirectPushDeployHarborHost)
utils.BeautifulPrintListWithTitle(errorLoadImageNameList, "errorLoadImageNameList")
utils.BeautifulPrintListWithTitle(errorPushImageNameList, "errorPushImageNameList")
}
func TestLoadSplitDepGzipImageToTargetHarbor(t *testing.T) {
errorLoadImageNameList, errorPushImageNameList := LoadSplitDepGzipImageToTargetHarbor(DirectPushDeployHarborHost)
utils.BeautifulPrintListWithTitle(errorLoadImageNameList, "errorLoadImageNameList")
utils.BeautifulPrintListWithTitle(errorPushImageNameList, "errorPushImageNameList")
}
func TestImageSyncEntity_PullFromEntityAndSyncConditionally(t *testing.T) {
imageSyncEntity := ImageSyncEntity{
ProjectVersion: "5.4.0",
DirectHarborHost: "36.134.71.138",
}
imageSyncResult := imageSyncEntity.PullFromEntityAndSyncConditionally()
utils.BeautifulPrint(imageSyncResult)
}

View File

@@ -0,0 +1,258 @@
package agent_operator
import (
v1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"strings"
"wdd.io/agent-common/utils"
)
type CmiiInterfaceConvert interface {
}
type CmiiPodInterface struct {
Name string
Namespace string
//ReplicaSetName string
ContainerImageMap map[string]string
PodIP string
HostIP string
NodeName string
RestartCountMap map[string]int32
RestartCount int32
ContainerName string
Image string
ImageTag string
GitBranch string
GitCommit string
PodStatus bool
PodPhase corev1.PodPhase
}
type CmiiDeploymentInterface struct {
Name string
Namespace string
AvailableReplicas int32
Replicas int32
ContainerImageMap map[string]string
ContainerName string
Image string
ImageTag string
GitBranch string
GitCommit string
StatusOk bool
}
type CmiiNodeInterface struct {
Name string
Hostname string
InternalIP string
KernelVersion string
OsImage string
Architecture string
KubeletVersion string
CpuCapacity string
MemoryCapacity string
PodCapacity string
StorageCapacity string
Labels map[string]string
Unschedulable bool
NodeStatus bool
MemoryPressure bool
DiskPressure bool
PIDPressure bool
NetworkUnavailable bool
}
func (deploy CmiiDeploymentInterface) Convert(deployment v1.Deployment) CmiiDeploymentInterface {
containers := deployment.Spec.Template.Spec.Containers
containerImageMap := make(map[string]string, len(containers))
if len(containers) > 1 {
log.WarnF("[CmiiDeploymentInterface Convert] - deployment [%s] [%s] container greater than one !", deployment.Namespace, deployment.Name)
}
for _, container := range containers {
containerImageMap[container.Name] = container.Image
deploy.Image = container.Image
deploy.ContainerName = container.Name
if strings.Contains(container.Image, ":8033") {
deploy.ImageTag = strings.Split(container.Image, ":")[2]
} else {
deploy.ImageTag = strings.Split(container.Image, ":")[1]
}
for _, envVar := range container.Env {
if strings.HasPrefix(envVar.Name, "GIT_BRANCH") {
deploy.GitBranch = envVar.Value
}
if strings.HasPrefix(envVar.Name, "GIT_COMMIT") {
deploy.GitCommit = envVar.Value
}
}
}
deploy.Name = deployment.Name
deploy.Namespace = deployment.Namespace
deploy.AvailableReplicas = deployment.Status.AvailableReplicas
deploy.Replicas = *deployment.Spec.Replicas
deploy.ContainerImageMap = containerImageMap
deploy.StatusOk = deployment.Status.AvailableReplicas == *deployment.Spec.Replicas
return deploy
}
func (deploy CmiiDeploymentInterface) ConvertFromStatefulSet(statefulSet v1.StatefulSet) CmiiDeploymentInterface {
containers := statefulSet.Spec.Template.Spec.Containers
containerImageMap := make(map[string]string, len(containers))
if len(containers) > 1 {
log.WarnF("[CmiiDeploymentInterface ConvertFromStatefulSet] - statefulSet [%s] [%s] container greater than one !", statefulSet.Namespace, statefulSet.Name)
}
for _, container := range containers {
containerImageMap[container.Name] = container.Image
deploy.Image = container.Image
deploy.ContainerName = container.Name
deploy.ImageTag = strings.Split(container.Image, ":")[1]
for _, envVar := range container.Env {
if strings.HasPrefix(envVar.Name, "GIT_BRANCH") {
deploy.GitBranch = envVar.Value
}
if strings.HasPrefix(envVar.Name, "GIT_COMMIT") {
deploy.GitCommit = envVar.Value
}
}
}
deploy.Name = statefulSet.Name
deploy.Namespace = statefulSet.Namespace
deploy.AvailableReplicas = statefulSet.Status.AvailableReplicas
deploy.Replicas = *statefulSet.Spec.Replicas
deploy.ContainerImageMap = containerImageMap
deploy.StatusOk = statefulSet.Status.AvailableReplicas == *statefulSet.Spec.Replicas
return deploy
}
func (pod CmiiPodInterface) Convert(podDetail corev1.Pod) CmiiPodInterface {
containers := podDetail.Spec.Containers
containerImageMap := make(map[string]string, len(containers))
if len(containers) > 1 {
log.WarnF("[CmiiDeploymentInterface Convert] - pod [%s] [%s] container greater than one !", podDetail.Namespace, podDetail.Name)
}
for _, container := range containers {
containerImageMap[container.Name] = container.Image
pod.Image = container.Image
pod.ContainerName = container.Name
if strings.Contains(container.Image, ":") {
pod.ImageTag = strings.Split(container.Image, ":")[1]
}
for _, envVar := range container.Env {
if strings.HasPrefix(envVar.Name, "GIT_BRANCH") {
pod.GitBranch = envVar.Value
}
if strings.HasPrefix(envVar.Name, "GIT_COMMIT") {
pod.GitCommit = envVar.Value
}
}
}
containerStatuses := podDetail.Status.ContainerStatuses
containerStatusMap := make(map[string]int32, len(containerStatuses))
for _, containerStatus := range containerStatuses {
containerStatusMap[containerStatus.Name] = containerStatus.RestartCount
pod.RestartCount = utils.MaxInt32(pod.RestartCount, containerStatus.RestartCount)
}
pod.Name = podDetail.Name
pod.Namespace = podDetail.Namespace
pod.ContainerImageMap = containerImageMap
pod.RestartCountMap = containerStatusMap
pod.PodIP = podDetail.Status.PodIP
pod.HostIP = podDetail.Status.HostIP
pod.NodeName = podDetail.Spec.NodeName
pod.PodPhase = podDetail.Status.Phase
switch podDetail.Status.Phase {
case corev1.PodFailed:
pod.PodStatus = false
break
case corev1.PodPending:
pod.PodStatus = false
break
case corev1.PodReasonUnschedulable:
pod.PodStatus = false
break
default:
pod.PodStatus = true
break
}
return pod
}
func (node CmiiNodeInterface) Convert(sourceNode corev1.Node) CmiiNodeInterface {
node.Name = sourceNode.Name
for _, nodeAddress := range sourceNode.Status.Addresses {
if nodeAddress.Type == corev1.NodeInternalIP {
node.InternalIP = nodeAddress.Address
}
if nodeAddress.Type == corev1.NodeHostName {
node.Hostname = nodeAddress.Address
}
}
node.KernelVersion = sourceNode.Status.NodeInfo.KernelVersion
node.OsImage = sourceNode.Status.NodeInfo.OSImage
node.KubeletVersion = sourceNode.Status.NodeInfo.KubeletVersion
node.Architecture = sourceNode.Status.NodeInfo.Architecture
node.CpuCapacity = sourceNode.Status.Capacity.Cpu().String()
node.MemoryCapacity = sourceNode.Status.Capacity.Memory().String()
node.PodCapacity = sourceNode.Status.Capacity.Pods().String()
node.StorageCapacity = sourceNode.Status.Capacity.Storage().String()
node.Labels = sourceNode.Labels
for _, nodeCondition := range sourceNode.Status.Conditions {
switch nodeCondition.Type {
case corev1.NodeReady:
node.NodeStatus = uniformNodeConditionStatus(nodeCondition.Status)
break
case corev1.NodeMemoryPressure:
node.MemoryPressure = uniformNodeConditionStatus(nodeCondition.Status)
break
case corev1.NodeDiskPressure:
node.DiskPressure = uniformNodeConditionStatus(nodeCondition.Status)
break
case corev1.NodePIDPressure:
node.PIDPressure = uniformNodeConditionStatus(nodeCondition.Status)
break
case corev1.NodeNetworkUnavailable:
node.NetworkUnavailable = uniformNodeConditionStatus(nodeCondition.Status)
break
}
}
node.Unschedulable = sourceNode.Spec.Unschedulable
return node
}
func uniformNodeConditionStatus(conditionType corev1.ConditionStatus) bool {
if conditionType == corev1.ConditionTrue {
return true
} else {
return false
}
}

View File

@@ -0,0 +1,866 @@
package agent_operator
import (
"bytes"
"context"
v1 "k8s.io/api/apps/v1"
autoscalingv1 "k8s.io/api/autoscaling/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/remotecommand"
"strings"
"sync"
"time"
"wdd.io/agent-common/logger"
"wdd.io/agent-common/utils"
"wdd.io/agent-operator/image"
)
var log = logger.Log
type CmiiK8sOperator struct {
DevClient *kubernetes.Clientset
CoreClient *kubernetes.Clientset
CurrentNamespace string
CurrentClient *kubernetes.Clientset
DevConfig *restclient.Config
CoreConfig *restclient.Config
CurrentConfig *restclient.Config
}
const (
dev = "uavcloud-dev"
devFlight = "uavcloud-devflight"
devOperation = "uavcloud-devoperation"
validation = "uavcloud-feature"
integration = "uavcloud-test"
uat = "uavcloud-uat"
demo = "uavcloud-demo"
uavms = "uavcloud-uavms"
workerThread = 4
)
func (op *CmiiK8sOperator) checkAndBuildCmiiK8sOperator() {
if op.DevClient == nil {
log.InfoF("[client] - build devFlight k8s operator client !")
devConfig, err := clientcmd.RESTConfigFromKubeConfig([]byte(CmiiDevK8sConfig))
if err != nil {
msg := "[client] - build devFlight k8s operator error !"
log.Error(msg)
panic(msg)
}
op.DevConfig = devConfig
op.DevClient, err = kubernetes.NewForConfig(devConfig)
if err != nil {
panic(err.Error())
}
}
if op.CoreClient == nil {
log.InfoF("[client] - build core k8s operator client !")
coreConfig, err := clientcmd.RESTConfigFromKubeConfig([]byte(CmiiCoreK8sConfig))
if err != nil {
msg := "[client] - build devFlight k8s operator error !"
log.Error(msg)
panic(msg)
}
op.CoreConfig = coreConfig
op.CoreClient, err = kubernetes.NewForConfig(coreConfig)
if err != nil {
panic(err.Error())
}
}
}
func (op *CmiiK8sOperator) changeOperatorEnv(cmiiEnv string) {
// ok
op.checkAndBuildCmiiK8sOperator()
// first key
op.CurrentNamespace = ""
if strings.Contains(cmiiEnv, "dev") {
if strings.Contains(cmiiEnv, "devf") {
op.CurrentNamespace = devFlight
} else if strings.Contains(cmiiEnv, "devo") {
op.CurrentNamespace = devOperation
} else {
op.CurrentNamespace = dev
}
}
if strings.Contains(cmiiEnv, "int") || strings.Contains(cmiiEnv, "test") {
op.CurrentNamespace = integration
}
if strings.Contains(cmiiEnv, "fe") || strings.Contains(cmiiEnv, "val") {
op.CurrentNamespace = validation
}
if strings.Contains(cmiiEnv, "uat") {
op.CurrentNamespace = uat
}
if strings.Contains(cmiiEnv, "demo") {
op.CurrentNamespace = demo
}
if strings.Contains(cmiiEnv, "uavms") {
op.CurrentNamespace = uavms
}
// key feature
if op.CurrentNamespace == "" {
op.CurrentNamespace = cmiiEnv
} else {
if strings.Contains(cmiiEnv, "dev") {
op.CurrentClient = op.DevClient
op.CurrentConfig = op.DevConfig
} else {
op.CurrentClient = op.CoreClient
op.CurrentConfig = op.CoreConfig
}
}
log.InfoF("[k8s env] - current env is => %s", op.CurrentNamespace)
}
func (op *CmiiK8sOperator) BuildCurrentClientFromConfig(realClientConfig string) {
log.InfoF("[BuildCurrentClientFromConfig] - build real k8s operator client !")
realEnvConfig, err := clientcmd.RESTConfigFromKubeConfig([]byte(realClientConfig))
if err != nil {
msg := "[BuildCurrentClientFromConfig] - build real k8s operator error !"
log.Error(msg)
panic(msg)
}
op.CurrentConfig = realEnvConfig
op.CurrentClient, err = kubernetes.NewForConfig(realEnvConfig)
if err != nil {
panic(err.Error())
}
}
func (op *CmiiK8sOperator) DeploymentAll(cmiiEnv string) []v1.Deployment {
op.changeOperatorEnv(cmiiEnv)
client := op.CurrentClient
deploymentList, err := client.AppsV1().Deployments(op.CurrentNamespace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
log.ErrorF("[DeploymentAll] - list deployment in [%s] [%s] error => %s", cmiiEnv, op.CurrentNamespace, err.Error())
}
deployments := deploymentList.Items
length := len(deployments)
log.InfoF("[DeploymentAll] - deployment in [%s] count is => %d", op.CurrentNamespace, length)
results := make([]v1.Deployment, length)
ccc := make(chan v1.Deployment, length)
var wg sync.WaitGroup
//var mutex sync.Mutex
worker := workerThread
if length <= worker {
for i, deployment := range deployments {
objectMeta := deployment.ObjectMeta
objectMeta.SetAnnotations(nil)
objectMeta.SetManagedFields(nil)
deployment.ObjectMeta = objectMeta
results[i] = deployment
}
return results
}
pinch := (length + worker - 1) / worker
wg.Add(worker)
for splice := 0; splice < worker; splice++ {
// 计算每个goroutine处理的切片段
start := splice * pinch
end := start + pinch
if end > length {
end = length
}
//log.DebugF("[DeploymentAll] - deployment pinch from [%d - %d]", start, end)
go func(deploymentList []v1.Deployment, start int, results *[]v1.Deployment) {
for _, deployment := range deploymentList {
objectMeta := deployment.ObjectMeta
objectMeta.SetAnnotations(nil)
objectMeta.SetManagedFields(nil)
deployment.ObjectMeta = objectMeta
ccc <- deployment
//i := *results
//i[index+start] = deployment
}
wg.Done()
}(deployments[start:end], start, &results)
}
go func() {
wg.Wait()
close(ccc)
}()
wg.Wait()
index := 0
for deployment := range ccc {
results[index] = deployment
index++
}
return results[:index]
}
func (op *CmiiK8sOperator) DeploymentAllInterface(cmiiEnv string) []CmiiDeploymentInterface {
op.changeOperatorEnv(cmiiEnv)
client := op.CurrentClient
deploymentList, err := client.AppsV1().Deployments(op.CurrentNamespace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
log.ErrorF("[DeploymentAllInterface] - list deployment in [%s] [%s] error => %s", cmiiEnv, op.CurrentNamespace, err.Error())
}
deployments := deploymentList.Items
length := len(deployments)
results := make([]CmiiDeploymentInterface, length)
ccc := make(chan CmiiDeploymentInterface, length)
var wg sync.WaitGroup
worker := workerThread
if length <= worker {
for i, deployment := range deployments {
objectMeta := deployment.ObjectMeta
objectMeta.SetAnnotations(nil)
objectMeta.SetManagedFields(nil)
deployment.ObjectMeta = objectMeta
results[i] = CmiiDeploymentInterface{}.Convert(deployment)
}
return results
}
pinch := length / worker
wg.Add(worker)
for splice := 0; splice < worker; splice++ {
go func(deploymentList []v1.Deployment) {
defer wg.Done()
for _, deployment := range deploymentList {
objectMeta := deployment.ObjectMeta
objectMeta.SetAnnotations(nil)
objectMeta.SetManagedFields(nil)
deployment.ObjectMeta = objectMeta
ccc <- CmiiDeploymentInterface{}.Convert(deployment)
}
}(deployments[splice*pinch : utils.MinInt((splice+1)*pinch, length)])
}
go func() {
wg.Wait()
close(ccc)
}()
index := 0
for deployment := range ccc {
results[index] = deployment
index++
}
return results[:index]
}
func (op *CmiiK8sOperator) DeploymentFizz(cmiiEnv, appFizz string) (fizzDeployment []v1.Deployment) {
deploymentAll := op.DeploymentAll(cmiiEnv)
if deploymentAll == nil {
log.ErrorF("[DeploymentFizz] - namespace [%s] can not get deployment [%s]", cmiiEnv, appFizz)
return nil
}
for _, deployment := range deploymentAll {
if strings.Contains(deployment.Name, appFizz) {
fizzDeployment = append(fizzDeployment, deployment)
}
}
return fizzDeployment
}
func (op *CmiiK8sOperator) DeploymentExist(cmiiEnv, appName string) (exists *v1.Deployment) {
op.changeOperatorEnv(cmiiEnv)
client := op.CurrentClient
deployment, err := client.AppsV1().Deployments(op.CurrentNamespace).Get(context.TODO(), appName, metav1.GetOptions{})
if err != nil {
log.ErrorF("[DeploymentExist] - deployments [%s] [%s] not exists ! %s", cmiiEnv, appName, err.Error())
return nil
}
return deployment
}
func (op *CmiiK8sOperator) DeploymentOneInterface(cmiiEnv, appName string) (deploy *CmiiDeploymentInterface) {
op.changeOperatorEnv(cmiiEnv)
client := op.CurrentClient
deploymentInterface := CmiiDeploymentInterface{}
deployment, err := client.AppsV1().Deployments(op.CurrentNamespace).Get(context.TODO(), appName, metav1.GetOptions{})
if err != nil {
log.ErrorF("[DeploymentExist] - deployments [%s] [%s] not exists ! %s", cmiiEnv, appName, err.Error())
return nil
}
convert := deploymentInterface.Convert(*deployment)
return &convert
}
func (op *CmiiK8sOperator) StatefulSetOneInterface(cmiiEnv, appName string) (deploy *CmiiDeploymentInterface) {
op.changeOperatorEnv(cmiiEnv)
client := op.CurrentClient
deploymentInterface := CmiiDeploymentInterface{}
statefulSet, err := client.AppsV1().StatefulSets(op.CurrentNamespace).Get(context.TODO(), appName, metav1.GetOptions{})
if err != nil {
log.ErrorF("[StatefulSetOneInterface] - stateful set [%s] [%s] not exists ! %s", cmiiEnv, appName, err.Error())
return nil
}
convert := deploymentInterface.ConvertFromStatefulSet(*statefulSet)
return &convert
}
func (op *CmiiK8sOperator) DeploymentScale(cmiiEnv, appName string, scaleCount int32) bool {
deployment := op.DeploymentOneInterface(cmiiEnv, appName)
client := op.CurrentClient
log.DebugF("[DeploymentScale] - start to scale [%s] [%s] to %d", deployment.Namespace, deployment.Name, scaleCount)
scale := &autoscalingv1.Scale{
ObjectMeta: metav1.ObjectMeta{
Name: deployment.Name,
Namespace: deployment.Namespace,
},
Spec: autoscalingv1.ScaleSpec{
Replicas: scaleCount,
},
}
updateScale, err := client.AppsV1().Deployments(deployment.Namespace).UpdateScale(
context.TODO(),
deployment.Name,
scale,
metav1.UpdateOptions{},
)
if err != nil {
log.ErrorF("[DeploymentScale] - scale error %s", err.Error())
return false
}
log.InfoF("[DeploymentScale] - scale of [%s] [%s] to %d success !", updateScale.Namespace, updateScale.Name, scaleCount)
return true
}
func (op *CmiiK8sOperator) DeploymentUpdateTag(cmiiEnv, appName, newTag string) bool {
if newTag == "" {
log.WarnF("[DeploymentUpdateTag] - can not update image tag to null!")
return false
}
deployment := op.DeploymentExist(cmiiEnv, appName)
if deployment == nil {
return false
}
containers := deployment.Spec.Template.Spec.Containers
if len(containers) == 1 {
// only update this kind
container := containers[0]
oldName := container.Image
split := strings.Split(container.Image, ":")
if strings.HasPrefix(container.Image, image.CmiiHarborPrefix) {
// harbor
container.Image = split[0] + ":" + newTag
} else if strings.Contains(container.Image, "8033") {
// 192.168.6.6:8033/rancher/k8s-dns-sidecar:v1.0.2
container.Image = split[0] + ":" + split[1] + ":" + newTag
}
log.DebugF("[DeploymentUpdateTag] - update [%s] [%s] from [%s] to [%s]", op.CurrentNamespace, appName, oldName, container.Image)
// re assign
deployment.Spec.Template.Spec.Containers[0] = container
// update
_, err := op.CurrentClient.AppsV1().Deployments(deployment.Namespace).Update(context.TODO(), deployment, metav1.UpdateOptions{})
if err != nil {
log.ErrorF("[DeploymentUpdateTag] - update [%s] [%s] from [%s] to [%s] error ! %s", op.CurrentNamespace, appName, split[1], container.Image, err.Error())
return false
}
} else if len(containers) == 2 {
log.ErrorF("[DeploymentUpdateTag] - cant update app with 2 containers !")
return false
}
return true
}
func (op *CmiiK8sOperator) DeploymentRestart(cmiiEnv, appName string) bool {
op.changeOperatorEnv(cmiiEnv)
result := true
deployment := op.DeploymentOneInterface(cmiiEnv, appName)
if deployment == nil {
log.ErrorF("[DeploymentRestart] - [%s] [%s] not exists !", cmiiEnv, appName)
return false
}
result = op.DeploymentScale(deployment.Namespace, deployment.Name, 0)
if !result {
return result
}
time.Sleep(time.Millisecond * 200)
result = op.DeploymentScale(deployment.Namespace, deployment.Name, deployment.Replicas)
if !result {
return result
}
return result
}
func (op *CmiiK8sOperator) DeploymentRestartByKill(cmiiEnv, appName string) bool {
deployment := op.DeploymentOneInterface(cmiiEnv, appName)
if deployment == nil {
log.ErrorF("[DeploymentRestart] - [%s] [%s] not exists !", cmiiEnv, appName)
return false
}
podList := op.PodByAppName(deployment.Namespace, deployment.Name)
if podList == nil {
log.ErrorF("[DeploymentRestart] - [%s] [%s] no pod success !", deployment.Namespace, deployment.Name)
return true
}
for _, podInterface := range podList {
if !op.PodDelete(cmiiEnv, podInterface.Name) {
log.ErrorF("[DeploymentRestart] - [%s] [%s] delete pod failed !", podInterface.Namespace, podInterface.Name)
} else {
log.DebugF("[DeploymentRestart] - [%s] [%s] delete pod success !", podInterface.Namespace, podInterface.Name)
}
}
return true
}
func (op *CmiiK8sOperator) DeploymentNew(cmiiEnv, appName string, waitTimeOut int) bool {
op.changeOperatorEnv(cmiiEnv)
//op.CurrentClient.AppsV1().Deployments(op.CurrentNamespace).Apply()
return true
}
func (op *CmiiK8sOperator) DeploymentStatusCheck(cmiiEnv, appName string, waitTimeOut int) bool {
op.changeOperatorEnv(cmiiEnv)
// 设置超时时间和时间间隔
timeout := time.After(time.Duration(waitTimeOut) * time.Second)
tick := time.Tick(time.Second)
// 监控Pod状态
for {
select {
case <-timeout:
log.ErrorF("[DeploymentStatusCheck] - [%s] [%s] 状态: 失败!", cmiiEnv, appName)
return false
case <-tick:
// check deployment exists
deployment := op.DeploymentOneInterface(cmiiEnv, appName)
if deployment == nil {
log.ErrorF("[DeploymentStatusCheck] - [%s] [%s] not exists !", cmiiEnv, appName)
return false
}
if deployment.AvailableReplicas == deployment.Replicas {
log.InfoF("[DeploymentStatusCheck] - [%s] [%s] Available: %d, Total: %d success !", deployment.Namespace, deployment.Name, deployment.AvailableReplicas, deployment.Replicas)
return true
}
log.DebugF("[DeploymentStatusCheck] - [%s] [%s] Available: %d, Total: %d waiting !", deployment.Namespace, deployment.Name, deployment.AvailableReplicas, deployment.Replicas)
}
}
}
func (op *CmiiK8sOperator) ReplicaSetExists(cmiiEnv, replicaSetName string) *v1.ReplicaSet {
op.changeOperatorEnv(cmiiEnv)
client := op.CurrentClient
replicaSet, err := client.AppsV1().ReplicaSets(op.CurrentNamespace).Get(context.TODO(), replicaSetName, metav1.GetOptions{})
if err != nil {
log.ErrorF("[ReplicaSetExists] - [%s] [%s] not exists !", cmiiEnv, replicaSetName)
return nil
}
return replicaSet
}
func (op *CmiiK8sOperator) ReplicaSetByAppName(cmiiEnv, appName string) (replicaList []v1.ReplicaSet) {
deploy := op.DeploymentExist(cmiiEnv, appName)
if deploy == nil {
log.ErrorF("[ReplicaSetByAppName] - [%s] [%s] app not exists !", cmiiEnv, appName)
return nil
}
labelSelector := metav1.FormatLabelSelector(deploy.Spec.Selector)
//Get the replica sets that belong to the deployment.
replicaSets, err := op.CurrentClient.AppsV1().ReplicaSets(op.CurrentNamespace).List(context.TODO(), metav1.ListOptions{
LabelSelector: labelSelector,
})
if err != nil {
log.ErrorF("[ReplicaSetByAppName] - [%s] [%s] list replicaset error %s", cmiiEnv, appName, err.Error())
return nil
}
for _, replicaSet := range replicaSets.Items {
replicaSet.SetManagedFields(nil)
replicaList = append(replicaList, replicaSet)
}
return replicaList
}
func (op *CmiiK8sOperator) PodAll(cmiiEnv string) []corev1.Pod {
op.changeOperatorEnv(cmiiEnv)
client := op.CurrentClient
podList, err := client.CoreV1().Pods(op.CurrentNamespace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
log.ErrorF("[PodAll] - list c in [%s] [%s] error => %s", cmiiEnv, op.CurrentNamespace, err.Error())
return nil
}
pods := podList.Items
length := len(pods)
results := make([]corev1.Pod, length)
ccc := make(chan corev1.Pod, length)
var wg sync.WaitGroup
worker := workerThread
if length <= worker {
for i, pod := range pods {
objectMeta := pod.ObjectMeta
objectMeta.SetAnnotations(nil)
objectMeta.SetManagedFields(nil)
pod.ObjectMeta = objectMeta
results[i] = pod
}
return results
}
pinch := length / worker
wg.Add(worker)
for splice := 0; splice < worker; splice++ {
go func(podList []corev1.Pod) {
defer wg.Done()
for _, pod := range podList {
objectMeta := pod.ObjectMeta
objectMeta.SetAnnotations(nil)
objectMeta.SetManagedFields(nil)
pod.ObjectMeta = objectMeta
ccc <- pod
}
}(pods[splice*pinch : utils.MinInt((splice+1)*pinch, length)])
}
go func() {
wg.Wait()
close(ccc)
}()
index := 0
for c := range ccc {
results[index] = c
index++
}
return results[:index]
}
func (op *CmiiK8sOperator) PodAllInterface(cmiiEnv string) []CmiiPodInterface {
op.changeOperatorEnv(cmiiEnv)
client := op.CurrentClient
podList, err := client.CoreV1().Pods(op.CurrentNamespace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
log.ErrorF("[PodAll] - list c in [%s] [%s] error => %s", cmiiEnv, op.CurrentNamespace, err.Error())
return nil
}
pods := podList.Items
length := len(pods)
results := make([]CmiiPodInterface, length)
ccc := make(chan CmiiPodInterface, length)
var wg sync.WaitGroup
podInterface := CmiiPodInterface{}
worker := workerThread
if length <= worker {
for i, pod := range pods {
objectMeta := pod.ObjectMeta
objectMeta.SetAnnotations(nil)
objectMeta.SetManagedFields(nil)
pod.ObjectMeta = objectMeta
results[i] = podInterface.Convert(pod)
}
return results
}
pinch := length / worker
wg.Add(worker)
for splice := 0; splice < worker; splice++ {
go func(podList []corev1.Pod) {
defer wg.Done()
for _, pod := range podList {
objectMeta := pod.ObjectMeta
objectMeta.SetAnnotations(nil)
objectMeta.SetManagedFields(nil)
pod.ObjectMeta = objectMeta
ccc <- podInterface.Convert(pod)
}
}(pods[splice*pinch : utils.MinInt((splice+1)*pinch, length)])
}
go func() {
wg.Wait()
close(ccc)
}()
index := 0
for c := range ccc {
results[index] = c
index++
}
return results[:index]
}
func (op *CmiiK8sOperator) PodByAppName(cmiiEnv, appName string) (podList []CmiiPodInterface) {
deploy := op.DeploymentExist(cmiiEnv, appName)
if deploy == nil {
log.ErrorF("[PodByAppName] - [%s] [%s] app not exists !", cmiiEnv, appName)
return nil
}
labelSelector := metav1.FormatLabelSelector(deploy.Spec.Selector)
//Get the replica sets that belong to the deployment.
pods, err := op.CurrentClient.CoreV1().Pods(op.CurrentNamespace).List(context.TODO(), metav1.ListOptions{
LabelSelector: labelSelector,
})
if err != nil {
log.ErrorF("[PodByAppName] - [%s] [%s] list pods error %s", cmiiEnv, appName, err.Error())
return nil
}
cmiiPodInterface := CmiiPodInterface{}
for _, pod := range pods.Items {
pod.SetManagedFields(nil)
podInterface := cmiiPodInterface.Convert(pod)
podList = append(podList, podInterface)
}
return podList
}
func (op *CmiiK8sOperator) PodByNodeName(cmiiEnv, nodeName string) (podList []CmiiPodInterface) {
node := op.NodeExists(cmiiEnv, nodeName)
if node == nil {
return nil
}
list, err := op.CurrentClient.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{
FieldSelector: "spec.nodeName=" + nodeName,
})
if err != nil {
log.ErrorF("[PodByNodeName] - [%s] [%s] list pod error %s !", cmiiEnv, nodeName, err.Error())
return nil
}
podInterface := CmiiPodInterface{}
for _, pod := range list.Items {
cmiiPodInterface := podInterface.Convert(pod)
podList = append(podList, cmiiPodInterface)
}
return podList
}
func (op *CmiiK8sOperator) PodFizz(cmiiEnv, appFizz string) (fizzPod []corev1.Pod) {
podAll := op.PodAll(cmiiEnv)
if podAll == nil {
log.ErrorF("[DeploymentFizz] - no app find in [%s] !", cmiiEnv)
return nil
}
for _, pod := range podAll {
if strings.Contains(pod.Name, appFizz) {
fizzPod = append(fizzPod, pod)
}
}
return fizzPod
}
func (op *CmiiK8sOperator) PodDelete(cmiiEnv, podName string) bool {
op.changeOperatorEnv(cmiiEnv)
client := op.CurrentClient
pod, err := client.CoreV1().Pods(op.CurrentNamespace).Get(context.TODO(), podName, metav1.GetOptions{})
if err != nil {
log.ErrorF("[PodDelete] - [%s] [%s] not exists", cmiiEnv, podName)
return false
}
// pod exists
err = client.CoreV1().Pods(op.CurrentNamespace).Delete(context.TODO(), pod.Name, metav1.DeleteOptions{})
if err != nil {
log.ErrorF("[PodDelete] - [%s] [%s] delete error ! %s", cmiiEnv, podName, err.Error())
return false
}
return true
}
func (op *CmiiK8sOperator) PodExec(cmiiEnv string, podInterface CmiiPodInterface, commandList []string) (stdout, stderr *bytes.Buffer) {
op.changeOperatorEnv(cmiiEnv)
client := op.CurrentClient
execRequest := client.CoreV1().RESTClient().
Post().
Resource("pods").
Name(podInterface.Name).
Namespace(op.CurrentNamespace).
SubResource("exec").
VersionedParams(&corev1.PodExecOptions{
Stdin: false,
Stdout: true,
Stderr: true,
TTY: false,
Container: podInterface.ContainerName,
Command: commandList,
}, scheme.ParameterCodec)
stdout = &bytes.Buffer{}
stderr = &bytes.Buffer{}
//log.DebugF("PodExec] - [%s] [%s] exec %s, url %s", cmiiEnv, podInterface.Name, commandList, execRequest.URL())
exec, err := remotecommand.NewSPDYExecutor(op.CurrentConfig, "POST", execRequest.URL())
if err != nil {
log.ErrorF("[PodExec] - NewSPDYExecutor error => %s", err.Error())
return stdout, stderr
}
err = exec.Stream(remotecommand.StreamOptions{
Stdin: nil,
Stdout: stdout,
Stderr: stderr,
Tty: false,
TerminalSizeQueue: nil,
})
if err != nil {
log.ErrorF("[PodExec] - exec.Stream error => %s", err.Error())
}
return stdout, stderr
}
func (op *CmiiK8sOperator) NodeAll(cmiiEnv string) (nodeListR []corev1.Node) {
op.changeOperatorEnv(cmiiEnv)
client := op.CurrentClient
nodeList, err := client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
if err != nil {
log.ErrorF("[NodeAll] - [%s] list all node failed %s", cmiiEnv, err.Error())
return nil
}
for _, node := range nodeList.Items {
node.SetManagedFields(nil)
nodeListR = append(nodeListR, node)
}
return nodeListR
}
func (op *CmiiK8sOperator) NodeAllInterface(cmiiEnv string) (nodeList []CmiiNodeInterface) {
nodeListR := op.NodeAll(cmiiEnv)
nodeInterface := CmiiNodeInterface{}
for _, node := range nodeListR {
nodeList = append(nodeList, nodeInterface.Convert(node))
}
return nodeList
}
func (op *CmiiK8sOperator) NodeExists(cmiiEnv, nodeName string) (node *CmiiNodeInterface) {
op.changeOperatorEnv(cmiiEnv)
client := op.CurrentClient
nodeInterface := CmiiNodeInterface{}
nodeList, err := client.CoreV1().Nodes().Get(context.TODO(), nodeName, metav1.GetOptions{})
if err != nil {
log.ErrorF("[NodeExists] - [%s] [%s] not exists !", cmiiEnv, nodeName)
return nil
}
convert := nodeInterface.Convert(*nodeList)
return &convert
}

View File

@@ -0,0 +1,292 @@
package agent_operator
import (
"bufio"
"fmt"
"testing"
"time"
"wdd.io/agent-common/assert"
"wdd.io/agent-common/utils"
)
func TestCmiiK8sOperator_DeploymentAll(t *testing.T) {
start := time.Now()
deploymentList := CmiiOperator.DeploymentAll("devflight")
elapsed := time.Since(start).Milliseconds()
fmt.Printf("执行耗时: %d ms\n", elapsed)
var nameList []string
count := 1
for _, deployment := range deploymentList {
if deployment.Spec.Replicas != nil {
count++
}
nameList = append(nameList, deployment.Name)
}
t.Logf("deployment list lenght is => %d", count)
t.Logf("deployment name list are => %d", count)
utils.BeautifulPrint(nameList)
//for _, deployment := range deploymentList {
// utils.BeautifulPrint(deployment)
// println()
//}
}
func TestCmiiK8sOperator_DeploymentAllInterface(t *testing.T) {
start := time.Now()
deploymentList := CmiiOperator.DeploymentAllInterface("devflight")
elapsed := time.Since(start).Milliseconds()
fmt.Printf("执行耗时: %d ms\n", elapsed)
t.Logf("deployment list lenght is => %d", len(deploymentList))
for _, deployment := range deploymentList {
utils.BeautifulPrint(deployment)
println()
}
}
func TestCmiiK8sOperator_DeploymentFizz(t *testing.T) {
start := time.Now()
deploymentFizz := CmiiOperator.DeploymentFizz("int", "cmii-suav-supervision")
elapsed := time.Since(start).Milliseconds()
fmt.Printf("执行耗时: %d ms\n", elapsed)
t.Logf("deployment list lenght is => %d", len(deploymentFizz))
cmiiDeploymentInterface := CmiiDeploymentInterface{}
for _, pod := range deploymentFizz {
convert := cmiiDeploymentInterface.Convert(pod)
utils.BeautifulPrint(convert)
utils.BeautifulPrint(pod)
}
// elastic search
}
func TestCmiiK8sOperator_DeploymentScale(t *testing.T) {
start := time.Now()
CmiiOperator.DeploymentScale("devflight", "cmii-uav-depotautoreturn", 0)
elapsed := time.Since(start).Milliseconds()
fmt.Printf("执行耗时: %d ms\n", elapsed)
}
func TestCmiiK8sOperator_DeploymentUpdateTag(t *testing.T) {
start := time.Now()
CmiiOperator.DeploymentUpdateTag("demo", "cmii-uav-platform", "5.2.0-011001")
elapsed := time.Since(start).Milliseconds()
fmt.Printf("执行耗时: %d ms\n", elapsed)
}
func TestCmiiK8sOperator_DeploymentRestart(t *testing.T) {
cmiiEnv := "int"
appName := "cmii-uav-gis-server"
CmiiOperator.DeploymentRestart(cmiiEnv, appName)
utils.SplitLinePrint()
check := CmiiOperator.DeploymentStatusCheck(cmiiEnv, appName, 180)
assert.Equal(t, check, true, "deployment run failed!")
}
func TestCmiiK8sOperator_DeploymentRestartByKill(t *testing.T) {
cmiiEnv := "demo"
appName := "cmii-uav-platform"
kill := CmiiOperator.DeploymentRestartByKill(cmiiEnv, appName)
assert.Equal(t, kill, true, "deployment restart by kill failed !")
utils.SplitLinePrint()
check := CmiiOperator.DeploymentStatusCheck(cmiiEnv, appName, 180)
assert.Equal(t, check, true, "deployment run failed!")
}
func TestCmiiK8sOperator_DeploymentOneInterface(t *testing.T) {
start := time.Now()
deploy := CmiiOperator.DeploymentOneInterface("devflight", "cmii-uav-depotautoreturn")
elapsed := time.Since(start).Milliseconds()
fmt.Printf("执行耗时: %d ms\n", elapsed)
utils.BeautifulPrint(*deploy)
}
func TestCmiiK8sOperator_ReplicaSetExists(t *testing.T) {
cmiiEnv := "uavcloud-devflight"
appName := "cmii-admin-data-bf8f87cb7"
exists := CmiiOperator.ReplicaSetExists(cmiiEnv, appName)
utils.BeautifulPrint(*exists)
}
func TestCmiiK8sOperator_ReplicaSetByAppName(t *testing.T) {
cmiiEnv := "uavcloud-devflight"
appName := "cmii-admin-data"
exists := CmiiOperator.ReplicaSetByAppName(cmiiEnv, appName)
for _, replicaSet := range exists {
utils.BeautifulPrint(replicaSet)
}
}
func TestCmiiK8sOperator_PodAll(t *testing.T) {
start := time.Now()
podList := CmiiOperator.PodAll("devflight")
elapsed := time.Since(start).Milliseconds()
fmt.Printf("执行耗时: %d ms\n", elapsed)
for _, pod := range podList {
println()
utils.BeautifulPrint(pod)
println()
break
}
}
func TestCmiiK8sOperator_PodFizz(t *testing.T) {
start := time.Now()
podList := CmiiOperator.PodFizz("devflight", "cmii-uav-data-post-process")
elapsed := time.Since(start).Milliseconds()
fmt.Printf("执行耗时: %d ms\n", elapsed)
t.Logf("pod list lenght is => %d", len(podList))
cmiiPodInterface := CmiiPodInterface{}
for _, pod := range podList {
println()
utils.BeautifulPrint(pod)
println()
convert := cmiiPodInterface.Convert(pod)
utils.BeautifulPrint(convert)
}
}
func TestCmiiK8sOperator_PodByAppName(t *testing.T) {
cmiiEnv := "uat"
appName := "cmii-admin-data"
exists := CmiiOperator.PodByNodeName(cmiiEnv, appName)
for _, podInterface := range exists {
utils.BeautifulPrint(podInterface)
}
}
func TestCmiiK8sOperator_PodFizz2(t *testing.T) {
start := time.Now()
podList := CmiiOperator.PodFizz("devflight", "notice")
elapsed := time.Since(start).Milliseconds()
fmt.Printf("执行耗时: %d ms\n", elapsed)
t.Logf("pod list lenght is => %d", len(podList))
podInterface := CmiiPodInterface{}
for _, pod := range podList {
convert := podInterface.Convert(pod)
println()
utils.BeautifulPrint(&convert)
println()
}
}
func TestCmiiK8sOperator_PodByNodeName(t *testing.T) {
cmiiEnv := "uat"
nodeName := "test-03.ecs.io"
exists := CmiiOperator.PodByNodeName(cmiiEnv, nodeName)
exists = FilterAllCmiiPodSoft(exists)
for _, podInterface := range exists {
utils.BeautifulPrint(podInterface)
if !podInterface.PodStatus {
podDelete := CmiiOperator.PodDelete(podInterface.Namespace, podInterface.Name)
assert.Equal(t, podDelete, true, "delete pod failed !")
}
}
}
func TestCmiiK8sOperator_PodExec(t *testing.T) {
podList := CmiiOperator.PodByAppName(devFlight, "cmii-uav-gateway")
stdout, stderr := CmiiOperator.PodExec(devFlight, podList[0], []string{
"env",
})
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
// Get the current line
line := scanner.Text()
// Check if the current line contains the search term
fmt.Println(line)
}
utils.SplitLinePrint()
scanner = bufio.NewScanner(stderr)
for scanner.Scan() {
// Get the current line
line := scanner.Text()
// Check if the current line contains the search term
fmt.Println(line)
}
}
func TestCmiiK8sOperator_DeploymentStatusCheck(t *testing.T) {
cmiiEnv := "devflight"
appName := "cmii-uav-gateway"
check := CmiiOperator.DeploymentStatusCheck(cmiiEnv, appName, 180)
assert.Equal(t, check, true, "deployment run failed!")
}
func TestCmiiK8sOperator_NodeAll(t *testing.T) {
start := time.Now()
nodeList := CmiiOperator.NodeAll("dev")
elapsed := time.Since(start).Milliseconds()
fmt.Printf("执行耗时: %d ms\n", elapsed)
for _, node := range nodeList {
println()
utils.BeautifulPrint(node)
println()
}
}
func TestCmiiK8sOperator_NodeAllInterface(t *testing.T) {
cmiiNodeInterfaces := CmiiOperator.NodeAllInterface("uat")
for _, nodeInterface := range cmiiNodeInterfaces {
println()
utils.BeautifulPrint(nodeInterface)
println()
}
}

View File

@@ -0,0 +1,26 @@
{
"docker.io/bitnami/redis": "6.2.6-debian-10-r0",
"docker.io/bitnami/redis": "6.2.14-debian-11-r1",
"docker.io/bitnami/mysql": "8.0.35-debian-11-r1",
"docker.io/bitnami/mysql": "8.1.0-debian-11-r42",
"docker.io/simonrupf/chronyd": "0.4.3",
"docker.io/bitnami/bitnami-shell": "10-debian-10-r140",
"docker.io/bitnami/bitnami-shell": "11-debian-11-r136",
"docker.io/bitnami/rabbitmq": "3.9.12-debian-10-r3",
"docker.io/bitnami/rabbitmq": "3.11.26-debian-11-r2",
"docker.io/ossrs/srs": "v4.0.136",
"docker.io/emqx/emqx": "4.2.12",
"docker.io/nacos/nacos-server": "v2.1.2",
"docker.io/nacos/nacos-server": "v2.1.2-slim",
"docker.io/mongo": "5.0",
"docker.io/rabbitmq": "3.9-management",
"docker.io/bitnami/minio": "2022.5.4",
"docker.io/bitnami/minio": "2023.5.4",
"docker.io/simonrupf/chronyd": "0.4.3",
"docker.io/kubernetesui/dashboard": "v2.0.1",
"docker.io/kubernetesui/metrics-scraper": "v1.0.4",
"docker.io/ossrs/srs": "v4.0-r3",
"docker.io/nginx": "1.21.3",
"docker.io/redis": "6.0.20-alpine",
"docker.io/dyrnq/nfs-subdir-external-provisioner": "v4.0.2"
}

View File

@@ -0,0 +1,58 @@
{
"rancher/backup-restore-operator": "v1.0.3",
"rancher/calico-cni": "v3.17.2",
"rancher/calico-ctl": "v3.17.2",
"rancher/calico-kube-controllers": "v3.17.2",
"rancher/calico-node": "v3.17.2",
"rancher/calico-pod2daemon-flexvol": "v3.17.2",
"rancher/cis-operator": "v1.0.3",
"rancher/coredns-coredns": "1.8.0",
"rancher/coreos-etcd": "v3.4.14-rancher1",
"rancher/coreos-kube-state-metrics": "v1.9.7",
"rancher/coreos-prometheus-config-reloader": "v0.39.0",
"rancher/coreos-prometheus-operator": "v0.39.0",
"rancher/externalip-webhook": "v0.1.6",
"rancher/flannel-cni": "v0.3.0-rancher6",
"rancher/coreos-flannel": "v0.13.0-rancher1",
"rancher/fleet-agent": "v0.3.4",
"rancher/fleet": "v0.3.4",
"rancher/fluentd": "v0.1.24",
"rancher/grafana-grafana": "7.1.5",
"rancher/hyperkube": "v1.20.4-rancher1",
"rancher/jimmidyson-configmap-reload": "v0.3.0",
"rancher/k8s-dns-dnsmasq-nanny": "1.15.2",
"rancher/k8s-dns-kube-dns": "1.15.2",
"rancher/k8s-dns-node-cache": "1.15.13",
"rancher/k8s-dns-sidecar": "1.15.2",
"rancher/klipper-lb": "v0.1.2",
"rancher/kube-api-auth": "v0.1.4",
"rancher/kubectl": "v1.20.4",
"rancher/kubernetes-external-dns": "v0.7.3",
"rancher/cluster-proportional-autoscaler": "1.8.1",
"rancher/library-busybox": "1.32.1",
"rancher/library-nginx": "1.19.2-alpine",
"rancher/library-traefik": "1.7.19",
"rancher/local-path-provisioner": "v0.0.14",
"rancher/log-aggregator": "v0.1.7",
"rancher/istio-kubectl": "1.5.10",
"rancher/metrics-server": "v0.4.1",
"rancher/configmap-reload": "v0.3.0-rancher4",
"rancher/nginx-ingress-controller-defaultbackend": "1.5-rancher1",
"rancher/nginx-ingress-controller": "nginx-0.43.0-rancher1",
"rancher/opa-gatekeeper": "v3.1.0-beta.7",
"rancher/openzipkin-zipkin": "2.14.2",
"rancher/pause": "3.2",
"rancher/plugins-docker": "18.09",
"rancher/prom-alertmanager": "v0.21.0",
"rancher/prom-node-exporter": "v1.0.1",
"rancher/prom-prometheus": "v2.18.2",
"rancher/prometheus-auth": "v0.2.1",
"rancher/rancher-agent": "v2.5.7",
"rancher/rancher-webhook": "v0.1.0-beta9",
"rancher/rancher": "v2.5.7",
"rancher/rke-tools": "v0.1.72",
"rancher/security-scan": "v0.1.14",
"rancher/shell": "v0.1.6",
"rancher/sonobuoy-sonobuoy": "v0.16.3",
"rancher/system-upgrade-controller": "v0.6.2"
}

View File

@@ -0,0 +1,90 @@
package deploy
import (
"bytes"
"fmt"
v1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
appsv1 "k8s.io/client-go/applyconfigurations/apps/v1"
"sigs.k8s.io/yaml"
"text/template"
"wdd.io/agent-common/utils"
)
type CommonEnvironmentConfig struct {
WebIP string
WebPort string
HarborIP string
HarborPort string
}
type CmiiBackendDeploymentConfig struct {
Namespace string
AppName string
ImageTag string
TagVersion string
Replicas string
NodePort string
NeedPvcCache bool
CustomJvmOpt string
}
type CmiiFrontendDeploymentConfig struct {
Namespace string
AppName string
ImageTag string
TagVersion string
Replicas string
ShortName string
}
func (backend CmiiBackendDeploymentConfig) ParseToApplyConf() *appsv1.DeploymentApplyConfiguration {
// 解析模板
tmpl, err := template.New("cmiiBackendDeploymentTemplate").Parse(cmiiBackendDeploymentTemplate)
if err != nil {
panic(err)
}
// 应用数据并打印结果
var result bytes.Buffer
err = tmpl.Execute(&result, backend)
if err != nil {
panic(err)
}
// 创建Deployment对象
deployment := v1.Deployment{}
err = yaml.Unmarshal(result.Bytes(), &deployment)
if err != nil {
panic(err)
}
utils.BeautifulPrint(&deployment)
// service
parse, err := template.New("cmiiBackendServiceTemplate").Parse(cmiiBackendServiceTemplate)
if err != nil {
panic(err)
}
// 应用数据并打印结果
var resulta bytes.Buffer
err = parse.Execute(&resulta, backend)
if err != nil {
panic(err)
}
fmt.Println(resulta.String())
// 创建Deployment对象
service := corev1.Service{}
err = yaml.Unmarshal(resulta.Bytes(), &service)
if err != nil {
panic(err)
}
utils.BeautifulPrint(&service)
return nil
}

View File

@@ -0,0 +1,263 @@
package deploy
const cmiiBackendDeploymentTemplate = `
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .AppName }}
namespace: {{ .Namespace }}
labels:
cmii.type: backend
cmii.app: {{ .AppName }}
octopus/control: backend-app-1.0.0
app.kubernetes.io/managed-by: octopus/control
app.kubernetes.io/app-version: {{ .TagVersion }}
spec:
replicas: {{ .Replicas }}
strategy:
rollingUpdate:
maxUnavailable: 1
selector:
matchLabels:
cmii.type: backend
cmii.app: {{ .AppName }}
template:
metadata:
labels:
cmii.type: backend
cmii.app: {{ .AppName }}
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: uavcloud.env
operator: In
values:
- demo
imagePullSecrets:
- name: harborsecret
containers:
- name: {{ .AppName }}
image: "harbor.cdcyy.com.cn/cmii/{{ .AppName }}:{{ .ImageTag }}"
imagePullPolicy: Always
env:
- name: K8S_NAMESPACE
value: {{ .Namespace }}
- name: APPLICATION_NAME
value: {{ .AppName }}
- name: CUST_JAVA_OPTS
value: "-Xms500m -Xmx1500m -Dlog4j2.formatMsgNoLookups=true"
- name: NACOS_REGISTRY
value: "helm-nacos:8848"
- name: NACOS_DISCOVERY_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: NACOS_DISCOVERY_PORT
value: "8080"
- name: BIZ_CONFIG_GROUP
value: {{ .TagVersion }}
- name: SYS_CONFIG_GROUP
value: {{ .TagVersion }}
- name: IMAGE_VERSION
value: {{ .TagVersion }}
- name: NACOS_USERNAME
value: "developer"
- name: NACOS_PASSWORD
value: "Deve@9128201"
ports:
- name: pod-port
containerPort: 8080
protocol: TCP
resources:
limits:
memory: 2Gi
cpu: 2
requests:
memory: 1Gi
cpu: 200m
livenessProbe:
httpGet:
path: /cmii/ping
port: pod-port
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 20
successThreshold: 1
failureThreshold: 3
readinessProbe:
httpGet:
path: /cmii/ping
port: pod-port
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 20
successThreshold: 1
failureThreshold: 3
startupProbe:
httpGet:
path: /cmii/ping
port: pod-port
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 3
periodSeconds: 20
successThreshold: 1
failureThreshold: 5
volumeMounts:
- name: glusterfs-backend-log-volume
mountPath: /cmii/logs
readOnly: false
subPath: {{ .Namespace }}/{{ .AppName }}
{{- if .NeedPvcCache }}
- name: data-cache-volume
mountPath: /cmii/cache
readOnly: false
subPath: {{ .Namespace }}/{{ .AppName }}
{{- end }}
volumes:
- name: glusterfs-backend-log-volume
persistentVolumeClaim:
claimName: glusterfs-backend-log-pvc
{{- if .NeedPvcCache }}
- name: data-cache-volume
persistentVolumeClaim:
claimName: {{ .AppName }}-cache
{{- end }}
`
const cmiiBackendServiceTemplate = `
apiVersion: v1
kind: Service
metadata:
name: {{ .AppName }}
namespace: {{ .Namespace }}
labels:
cmii.type: backend
cmii.app: {{ .AppName }}
octopus/control: backend-app-1.0.0
app.kubernetes.io/managed-by: octopus/control
app.kubernetes.io/app-version: {{ .TagVersion }}
spec:
{{- if .NodePort }}
type: NodePort
{{- else }}
type: ClusterIP
{{- end }}
selector:
cmii.type: backend
cmii.app: {{ .AppName }}
ports:
- name: backend-tcp
port: 8080
protocol: TCP
targetPort: 8080
{{- if .NodePort }}
nodePort: {{ .NodePort }}
{{- end }}
`
const cmiiBackendPVCTemplate = `
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ .AppName }}-cache
namespace: {{ .Namespace }}
labels:
cmii.type: backend
cmii.app: {{ .AppName }}
octopus/control: backend-app-1.0.0
app.kubernetes.io/managed-by: octopus/control
app.kubernetes.io/app-version: {{ .TagVersion }}
spec:
storageClassName: nfs-prod-distribute
accessModes:
- ReadWriteMany
volumeMode: Filesystem
resources:
requests:
storage: 15Gi
`
const cmiiFrontendDeploymentTemplate = `
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .AppName }}
namespace: {{ .Namespace }}
labels:
cmii.type: frontend
cmii.app: {{ .AppName }}
octopus/control: frontend-app-1.0.0
app.kubernetes.io/managed-by: octopus/control
app.kubernetes.io/app-version: {{ .TagVersion }}
spec:
replicas: {{ .Replicas }}
strategy:
rollingUpdate:
maxUnavailable: 1
selector:
matchLabels:
cmii.type: frontend
cmii.app: {{ .AppName }}
template:
metadata:
labels:
cmii.type: frontend
cmii.app: {{ .AppName }}
spec:
imagePullSecrets:
- name: harborsecret
containers:
- name: {{ .AppName }}
image: "harbor.cdcyy.com.cn/cmii/{{ .AppName }}:{{ .ImageTag }}"
imagePullPolicy: Always
env:
- name: K8S_NAMESPACE
value: {{ .Namespace }}
- name: APPLICATION_NAME
value: {{ .AppName }}
ports:
- name: platform-9528
containerPort: 9528
protocol: TCP
resources:
limits:
cpu: "1"
memory: 1Gi
requests:
cpu: 500m
memory: 500Mi
volumeMounts:
- name: nginx-conf
mountPath: /usr/local/nginx/conf/nginx.conf
subPath: nginx.conf
- name: default-nginx-conf
mountPath: /etc/nginx/conf.d/default.conf
subPath: default.conf
- name: tenant-prefix
subPath: ingress-config.js
mountPath: /home/cmii-platform/dist/ingress-config.js
volumes:
- name: nginx-conf
configMap:
name: nginx-cm
items:
- key: nginx.conf
path: nginx.conf
- name: default-nginx-conf
configMap:
name: default-nginx-cm
items:
- key: default.conf
path: default.conf
- name: tenant-prefix
configMap:
name: tenant-prefix-{{ .ShortName }}
items:
- key: ingress-config.js
path: ingress-config.js
`

View File

@@ -0,0 +1,19 @@
package deploy
import "testing"
func TestCmiiBackendDeploymentConfig_ParseToApplyConf(t *testing.T) {
deploymentConfig := CmiiBackendDeploymentConfig{
Namespace: "uavcloud-dev",
AppName: "cmii-uav-gateway",
ImageTag: "5.2.0-123",
TagVersion: "5.2.0",
Replicas: "2",
NodePort: "31213",
NeedPvcCache: true,
}
deploymentConfig.ParseToApplyConf()
}

77
agent-operator/go.mod Normal file
View File

@@ -0,0 +1,77 @@
module wdd.io/agent-operator
go 1.22.1
require (
github.com/docker/docker v20.10.17+incompatible
github.com/docker/go-units v0.4.0
github.com/klauspost/pgzip v1.2.6
github.com/minio/minio-go v6.0.14+incompatible
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
github.com/morikuni/aec v1.0.0
k8s.io/api v0.29.1
k8s.io/apimachinery v0.29.1
k8s.io/client-go v0.29.1
sigs.k8s.io/yaml v1.4.0
wdd.io/agent-common v0.0.0
)
replace wdd.io/agent-common => ../agent-common
require (
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.uber.org/multierr v1.10.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.16.0 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/oauth2 v0.10.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/term v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.16.1 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.5.1 // indirect
k8s.io/klog/v2 v2.110.1 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
)

226
agent-operator/go.sum Normal file
View File

@@ -0,0 +1,226 @@
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE=
github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/minio/minio-go v6.0.14+incompatible h1:fnV+GD28LeqdN6vT2XdGKW8Qe/IfjJDswNVuni6km9o=
github.com/minio/minio-go v6.0.14+incompatible/go.mod h1:7guKYtitv8dktvNUGrhzmNlA5wrAABTQXCoesZdFQO8=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc=
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec=
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
k8s.io/api v0.29.1 h1:DAjwWX/9YT7NQD4INu49ROJuZAAAP/Ijki48GUPzxqw=
k8s.io/api v0.29.1/go.mod h1:7Kl10vBRUXhnQQI8YR/R327zXC8eJ7887/+Ybta+RoQ=
k8s.io/apimachinery v0.29.1 h1:KY4/E6km/wLBguvCZv8cKTeOwwOBqFNjwJIdMkMbbRc=
k8s.io/apimachinery v0.29.1/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU=
k8s.io/client-go v0.29.1 h1:19B/+2NGEwnFLzt0uB5kNJnfTsbV8w6TgQRz9l7ti7A=
k8s.io/client-go v0.29.1/go.mod h1:TDG/psL9hdet0TI9mGyHJSgRkW3H9JZk2dNEUS7bRks=
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

View File

@@ -0,0 +1,233 @@
package image
var MiddlewareAmd64 = []string{
"bitnami/redis:6.2.6-debian-10-r0",
"bitnami/redis:6.2.14-debian-11-r1",
"bitnami/mysql:8.0.35-debian-11-r1",
"bitnami/mysql:8.1.0-debian-11-r42",
"simonrupf/chronyd:0.4.3",
"bitnami/bitnami-shell:10-debian-10-r140",
"bitnami/bitnami-shell:11-debian-11-r136",
"bitnami/rabbitmq:3.9.12-debian-10-r3",
"bitnami/rabbitmq:3.11.26-debian-11-r2",
"ossrs/srs:v4.0.136",
"ossrs/srs:v5.0.195",
"ossrs/srs:v4.0-r3",
"emqx/emqx:4.2.12",
"nacos/nacos-server:v2.1.2",
"nacos/nacos-server:v2.1.2-slim",
"mongo:5.0",
"rabbitmq:3.9-management",
"bitnami/minio:2022.5.4",
"bitnami/minio:2023.5.4",
"kubernetesui/dashboard:v2.0.1",
"kubernetesui/metrics-scraper:v1.0.4",
"nginx:1.21.3",
"redis:6.0.20-alpine",
"dyrnq/nfs-subdir-external-provisioner:v4.0.2",
"jerrychina2020/rke-tools:v0.175-linux",
"busybox:latest",
}
var Rancher1204Amd64 = []string{
"rancher/backup-restore-operator:v1.0.3",
"rancher/calico-cni:v3.17.2",
"rancher/calico-ctl:v3.17.2",
"rancher/calico-kube-controllers:v3.17.2",
"rancher/calico-node:v3.17.2",
"rancher/calico-pod2daemon-flexvol:v3.17.2",
"rancher/cis-operator:v1.0.3",
"rancher/cluster-proportional-autoscaler:1.7.1",
"rancher/coredns-coredns:1.8.0",
"rancher/coreos-etcd:v3.4.14-rancher1",
"rancher/coreos-kube-state-metrics:v1.9.7",
"rancher/coreos-prometheus-config-reloader:v0.39.0",
"rancher/coreos-prometheus-operator:v0.39.0",
"rancher/externalip-webhook:v0.1.6",
"rancher/flannel-cni:v0.3.0-rancher6",
"rancher/coreos-flannel:v0.13.0-rancher1",
"rancher/fleet-agent:v0.3.4",
"rancher/fleet:v0.3.4",
"rancher/fluentd:v0.1.24",
"rancher/grafana-grafana:7.1.5",
"rancher/hyperkube:v1.20.4-rancher1",
"rancher/jimmidyson-configmap-reload:v0.3.0",
"rancher/k8s-dns-dnsmasq-nanny:1.15.2",
"rancher/k8s-dns-kube-dns:1.15.2",
"rancher/k8s-dns-node-cache:1.15.13",
"rancher/k8s-dns-sidecar:1.15.2",
"rancher/klipper-lb:v0.1.2",
"rancher/kube-api-auth:v0.1.4",
"rancher/kubectl:v1.20.4",
"rancher/kubernetes-external-dns:v0.7.3",
"rancher/cluster-proportional-autoscaler:1.8.1",
"rancher/library-busybox:1.31.1",
"rancher/library-busybox:1.32.1",
"rancher/library-nginx:1.19.2-alpine",
"rancher/library-traefik:1.7.19",
"rancher/local-path-provisioner:v0.0.11",
"rancher/local-path-provisioner:v0.0.14",
"rancher/local-path-provisioner:v0.0.19",
"rancher/log-aggregator:v0.1.7",
"rancher/istio-kubectl:1.5.10",
"rancher/metrics-server:v0.4.1",
"rancher/configmap-reload:v0.3.0-rancher4",
"rancher/nginx-ingress-controller-defaultbackend:1.5-rancher1",
"rancher/nginx-ingress-controller:nginx-0.43.0-rancher1",
"rancher/opa-gatekeeper:v3.1.0-beta.7",
"rancher/openzipkin-zipkin:2.14.2",
"rancher/pause:3.2",
"rancher/plugins-docker:18.09",
"rancher/prom-alertmanager:v0.21.0",
"rancher/prom-node-exporter:v1.0.1",
"rancher/prom-prometheus:v2.18.2",
"rancher/prometheus-auth:v0.2.1",
"rancher/rancher-agent:v2.5.7",
"rancher/rancher-webhook:v0.1.0-beta9",
"rancher/rancher:v2.5.7",
"rancher/rke-tools:v0.1.72",
"rancher/security-scan:v0.1.14",
"rancher/security-scan:v0.2.2",
"rancher/shell:v0.1.6",
"rancher/sonobuoy-sonobuoy:v0.16.3",
"rancher/system-upgrade-controller:v0.6.2",
}
var CmiiSRSImageList = []string{
"harbor.cdcyy.com.cn/cmii/cmii-live-operator:5.2.0",
"harbor.cdcyy.com.cn/cmii/cmii-srs-oss-adaptor:2023-SA",
}
var Cmii530DemoImageList = []string{
"cmii-admin-data:5.2.0",
"cmii-admin-gateway:5.2.0",
"cmii-admin-user:5.2.0",
"cmii-app-release:4.2.0-validation",
"cmii-open-gateway:5.2.0",
"cmii-suav-supervision:5.2.0",
"cmii-uav-airspace:5.2.0",
"cmii-uav-alarm:5.2.0",
"cmii-uav-autowaypoint:4.1.6-cm-0828",
"cmii-uav-brain:5.2.0",
"cmii-uav-cloud-live:5.2.0",
"cmii-uav-clusters:5.2.0",
"cmii-uav-cms:5.2.0",
"cmii-uav-data-post-process:5.2.0",
"cmii-uav-depotautoreturn:4.2.0",
"cmii-uav-developer:5.2.0-25858",
"cmii-uav-device:5.2.0",
"cmii-uav-emergency:5.2.0",
"cmii-uav-gateway:5.2.0",
"cmii-uav-gis-server:5.2.0",
"cmii-uav-grid-datasource:5.2.0-24810",
"cmii-uav-grid-engine:5.1.0",
"cmii-uav-grid-manage:5.1.0",
"cmii-uav-industrial-portfolio:5.2.0-25268-12",
"cmii-uav-integration:5.2.0-25447",
"cmii-uav-kpi-monitor:5.2.0",
"cmii-uav-logger:5.2.0",
"cmii-uav-material-warehouse:5.2.0",
"cmii-uav-mission:5.2.0-25840",
"cmii-uav-mqtthandler:5.2.0-25340-1",
"cmii-uav-notice:5.2.0",
"cmii-uav-oauth:5.2.0",
"cmii-uav-process:5.2.0",
"cmii-uav-surveillance:5.2.0-21794",
"cmii-uav-threedsimulation:5.2.0",
"cmii-uav-tower:5.3.0",
"cmii-uav-user:5.2.0",
"cmii-uav-waypoint:5.2.0-011102",
"cmii-suav-platform-supervision:5.2.0",
"cmii-suav-platform-supervisionh5:5.2.0",
"cmii-uav-platform:5.2.0",
"cmii-uav-platform-ai-brain:5.2.0",
"cmii-uav-platform-armypeople:5.2.0-24538",
"cmii-uav-platform-base:5.2.0",
"cmii-uav-platform-cms-portal:5.2.0",
"cmii-uav-platform-detection:5.2.0",
"cmii-uav-platform-emergency-rescue:5.2.0",
"cmii-uav-platform-hljtt:5.2.0",
"cmii-uav-platform-jiangsuwenlv:4.1.3-jiangsu-0427",
"cmii-uav-platform-logistics:5.2.0",
"cmii-uav-platform-media:5.2.0",
"cmii-uav-platform-multiterminal:5.2.0",
"cmii-uav-platform-mws:5.2.0",
"cmii-uav-platform-oms:5.2.0",
"cmii-uav-platform-open:5.2.0",
"cmii-uav-platform-qingdao:4.1.6-24238-qingdao",
"cmii-uav-platform-qinghaitourism:4.1.0-21377-0508",
"cmii-uav-platform-security:4.1.6",
"cmii-uav-platform-securityh5:5.2.0",
"cmii-uav-platform-seniclive:5.2.0",
"cmii-uav-platform-share:5.2.0",
"cmii-uav-platform-splice:5.2.0",
"cmii-uav-platform-threedsimulation:5.2.0-21392",
"cmii-uav-platform-visualization:5.2.0",
}
var Cmii520DemoImageList = []string{
"cmii-admin-data:5.2.0",
"cmii-admin-gateway:5.2.0",
"cmii-admin-user:5.2.0",
"cmii-app-release:4.2.0-validation",
"cmii-open-gateway:5.2.0",
"cmii-suav-supervision:5.2.0",
"cmii-uav-airspace:5.2.0",
"cmii-uav-alarm:5.2.0",
"cmii-uav-autowaypoint:4.1.6-cm-0828",
"cmii-uav-brain:5.2.0",
"cmii-uav-cloud-live:5.2.0",
"cmii-uav-clusters:5.2.0",
"cmii-uav-cms:5.2.0",
"cmii-uav-data-post-process:5.2.0",
"cmii-uav-depotautoreturn:4.2.0",
"cmii-uav-developer:5.2.0-25858",
"cmii-uav-device:5.2.0",
"cmii-uav-emergency:5.2.0",
"cmii-uav-gateway:5.2.0",
"cmii-uav-gis-server:5.2.0",
"cmii-uav-grid-datasource:5.2.0-24810",
"cmii-uav-grid-engine:5.1.0",
"cmii-uav-grid-manage:5.1.0",
"cmii-uav-industrial-portfolio:5.2.0-25268-12",
"cmii-uav-integration:5.2.0-25447",
"cmii-uav-kpi-monitor:5.2.0",
"cmii-uav-logger:5.2.0",
"cmii-uav-material-warehouse:5.2.0",
"cmii-uav-mission:5.2.0-25840",
"cmii-uav-mqtthandler:5.2.0-25340-1",
"cmii-uav-notice:5.2.0",
"cmii-uav-oauth:5.2.0",
"cmii-uav-process:5.2.0",
"cmii-uav-surveillance:5.2.0-21794",
"cmii-uav-threedsimulation:5.2.0",
"cmii-uav-tower:5.3.0",
"cmii-uav-user:5.2.0",
"cmii-uav-waypoint:5.2.0-011102",
"cmii-suav-platform-supervision:5.2.0",
"cmii-suav-platform-supervisionh5:5.2.0",
"cmii-uav-platform:5.2.0",
"cmii-uav-platform-ai-brain:5.2.0",
"cmii-uav-platform-armypeople:5.2.0-24538",
"cmii-uav-platform-base:5.2.0",
"cmii-uav-platform-cms-portal:5.2.0",
"cmii-uav-platform-detection:5.2.0",
"cmii-uav-platform-emergency-rescue:5.2.0",
"cmii-uav-platform-hljtt:5.2.0",
"cmii-uav-platform-jiangsuwenlv:4.1.3-jiangsu-0427",
"cmii-uav-platform-logistics:5.2.0",
"cmii-uav-platform-media:5.2.0",
"cmii-uav-platform-multiterminal:5.2.0",
"cmii-uav-platform-mws:5.2.0",
"cmii-uav-platform-oms:5.2.0",
"cmii-uav-platform-open:5.2.0",
"cmii-uav-platform-qingdao:4.1.6-24238-qingdao",
"cmii-uav-platform-qinghaitourism:4.1.0-21377-0508",
"cmii-uav-platform-security:4.1.6",
"cmii-uav-platform-securityh5:5.2.0",
"cmii-uav-platform-seniclive:5.2.0",
"cmii-uav-platform-share:5.2.0",
"cmii-uav-platform-splice:5.2.0",
"cmii-uav-platform-threedsimulation:5.2.0-21392",
"cmii-uav-platform-visualization:5.2.0",
}

View File

@@ -0,0 +1,569 @@
package image
import (
"bufio"
"context"
"encoding/json"
"errors"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/client"
"github.com/klauspost/pgzip"
"io"
"io/fs"
"os"
"strconv"
"strings"
"wdd.io/agent-common/logger"
"wdd.io/agent-common/utils"
)
var apiClient = newClient()
var log = logger.Log
const CmiiHarborPrefix = "harbor.cdcyy.com.cn/cmii/"
func newClient() *client.Client {
apiClient, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
log.ErrorF("[newClient] - new client failed ! => %s", err.Error())
panic(err)
}
defer apiClient.Close()
return apiClient
}
func GetRunningContainer() []types.Container {
return getContainerList(false)
}
func GetAllContainer() []types.Container {
return getContainerList(true)
}
func getContainerList(all bool) []types.Container {
containers, err := apiClient.ContainerList(context.Background(), types.ContainerListOptions{
Quiet: false,
Size: false,
All: all,
Latest: false,
Limit: 0,
Filters: filters.Args{},
})
if err != nil {
log.ErrorF("[getContainerList] - error => %s", err.Error())
}
return containers
}
//func SetDockerProxy(httpProxy string) {
// proxy_all := "HTTP_PROXY=" + httpProxy + " HTTPS_PROXY=" + httpProxy
//
// log.InfoF("[SetDockerProxy] - set docker proxy to %s", proxy_all)
//
// // Set the HTTP proxy for the Docker daemon
// configFile, err := apiClient.ConfigCreate(context.Background(), swarm.ConfigSpec{
// Annotations: swarm.Annotations{
// Name: "proxy.conf",
// },
// Data: []byte(proxy_all),
// })
// if err != nil {
// // 处理错误
// log.ErrorF("[SetDockerProxy] - set docker proxy error %s", err.Error())
// }
//
//
//
//
//}
func GetAll() []types.ImageSummary {
list, err := apiClient.ImageList(context.TODO(), types.ImageListOptions{
All: true,
Filters: filters.Args{},
})
if err != nil {
log.ErrorF("[ImageGetAll] --error => %s", err.Error())
}
return list
}
func GetByName(imageName string) *types.ImageSummary {
imageGetAll := GetAll()
for _, imageSummary := range imageGetAll {
for _, tag := range imageSummary.RepoTags {
if strings.Contains(tag, imageName) {
return &imageSummary
}
}
}
return nil
}
func Delete(imageName string) []types.ImageDeleteResponseItem {
imageGetByName := GetByName(imageName)
if imageGetByName == nil {
log.ErrorF("[ImageDelete] -- image not exists ! %s", imageGetByName.RepoTags)
return nil
}
remove, err := apiClient.ImageRemove(context.TODO(), imageGetByName.ID, types.ImageRemoveOptions{
Force: true,
PruneChildren: false,
})
if err != nil {
log.ErrorF("[ImageDelete] -- ImageRemove error ! %s", err.Error())
return nil
}
return remove
}
func PruneAllCmiiImages() (errorRemoveImageNameList []string) {
_, _ = apiClient.ImagesPrune(context.TODO(), filters.Args{})
imageGetAll := GetAll()
// ip:8033
//re := regexp.MustCompile(`\b(?:\d{1,3}\.){3}\d{1,3}:\d{1,4}`)
for _, imageSummary := range imageGetAll {
for _, repoTag := range imageSummary.RepoTags {
if strings.HasPrefix(repoTag, CmiiHarborPrefix) {
for _, tag := range imageSummary.RepoTags {
_, err := apiClient.ImageRemove(context.TODO(), imageSummary.ID, types.ImageRemoveOptions{
Force: true,
PruneChildren: true,
})
if err != nil {
log.ErrorF("[ImageDelete] -- ImageRemove error ! %s", err.Error())
errorRemoveImageNameList = append(errorRemoveImageNameList, tag)
}
log.InfoF("[ImageDelete] - image remove of [%s] success!", tag)
}
}
}
}
_, _ = apiClient.ImagesPrune(context.TODO(), filters.Args{})
return errorRemoveImageNameList
}
func TagFromSourceToTarget(sourceImageName, targetImageName string) bool {
getByName := GetByName(sourceImageName)
if getByName == nil {
log.ErrorF("[ImageTagFromSourceToTarget] - %s not exits !", sourceImageName)
return false
}
err := apiClient.ImageTag(context.TODO(), sourceImageName, targetImageName)
if err != nil {
log.ErrorF("[ImageTagFromSourceToTarget] - from %s to %s error %s", sourceImageName, targetImageName, err.Error())
}
log.InfoF("[ImageTagFromSourceToTarget] - from %s to %s success!", sourceImageName, targetImageName)
return true
}
func PushToOctopusKindHarbor(targetImageName string) (pushResult io.ReadCloser) {
if GetByName(targetImageName) == nil {
log.ErrorF("[ImagePushToOctopusKindHarbor] - %s not exits !", targetImageName)
return pushResult
}
pushResult, err := apiClient.ImagePush(context.TODO(), targetImageName, types.ImagePushOptions{
All: false,
RegistryAuth: "eyAidXNlcm5hbWUiOiAiYWRtaW4iLCAicGFzc3dvcmQiOiAiVjJyeVN0ckBuZ1BzcyIsICJlbWFpbCI6ICJpY2VAcXEuY29tIiB9Cg==",
PrivilegeFunc: nil,
Platform: "amd64",
})
if err != nil {
log.ErrorF("[ImagePushToOctopusKindHarbor] - push %s error %s", targetImageName, err.Error())
return nil
}
return pushResult
}
// TagFromListAndPushToCHarbor 需要支持 harbor.cdcyy.cn ip:8033 rancher/rancher:v2.5.7 nginx:latest
func TagFromListAndPushToCHarbor(referenceImageList []string, targetHarborHost string) (errorPushImageNameList []string) {
for _, imageName := range referenceImageList {
// check image
// harbor.cdcyy.cn
cmiiImageFullName := imageName
if strings.HasPrefix(imageName, "cmii") {
cmiiImageFullName = CmiiHarborPrefix + imageName
}
targetProject := "cmii"
if strings.HasPrefix(imageName, "rancher") {
targetProject = "rancher"
}
if strings.HasPrefix(imageName, CmiiHarborPrefix) {
//
imageName = strings.TrimPrefix(imageName, CmiiHarborPrefix)
} else {
// todo
if strings.Contains(imageName, "/") {
imageName = strings.Split(imageName, "/")[1]
}
}
targetImageName := targetHarborHost + ":8033/" + targetProject + "/" + imageName
if TagFromSourceToTarget(cmiiImageFullName, targetImageName) {
pushResult := PushToOctopusKindHarbor(targetImageName)
if pushResult == nil {
errorPushImageNameList = append(errorPushImageNameList, cmiiImageFullName)
log.InfoF("[ImageTagFromListAndPushToCHarbor] - push of %s error error !", targetImageName)
break
}
scanner := bufio.NewScanner(pushResult)
for scanner.Scan() {
}
log.InfoF("[ImageTagFromListAndPushToCHarbor] - push of %s success!", targetImageName)
} else {
errorPushImageNameList = append(errorPushImageNameList, cmiiImageFullName)
}
}
return errorPushImageNameList
}
func PullFromCmiiHarbor(imageName string) (pullResult io.ReadCloser) {
pullResult, err := apiClient.ImagePull(context.TODO(), imageName, types.ImagePullOptions{
All: false,
RegistryAuth: "eyAidXNlcm5hbWUiOiAicmFkMDJfZHJvbmUiLCAicGFzc3dvcmQiOiAiRHJvbmVAMTIzNCIsICJlbWFpbCI6ICJpY2VAcXEuY29tIiB9Cg==",
PrivilegeFunc: func() (string, error) {
return "authorization: Basic cmFkMDJfZHJvbmU6RHJvbmVAMTIzNA==", nil
},
Platform: "amd64",
})
if err != nil {
log.ErrorF("[ImagePullFromCmiiHarbor]- image pull of %s ,error => %s", imageName, err.Error())
return nil
}
return pullResult
}
func PullFromCmiiHarborByMap(imageVersionMap map[string]string, silentMode bool) (fullImageNameList, errorPullImageList []string) {
fullImageNameList = ConvertCMiiImageMapToList(imageVersionMap)
return fullImageNameList, PullFromFullNameList(fullImageNameList)
}
func PullCmiiFromFileJson(filePathName string) {
readFile, err := os.ReadFile(filePathName)
if err != nil {
log.ErrorF("[ImagePullCMiiFromFileJson] - file %s read error ! %s", filePathName, err.Error())
return
}
var resultMap map[string]string
err = json.Unmarshal(readFile, &readFile)
if err != nil {
log.ErrorF("[ImagePullCMiiFromFileJson] - file %s un marshal error ! %s", filePathName, err.Error())
return
}
for image, tag := range resultMap {
pullResult := PullFromCmiiHarbor(image + ":" + tag)
if pullResult == nil {
continue
}
scanner := bufio.NewScanner(pullResult)
for scanner.Scan() {
line := scanner.Text()
if strings.Contains(line, "\"status\":\"Pulling from") {
fmt.Println(line)
}
if strings.Contains(line, "Status: Image is up to date for") {
fmt.Println(line)
}
}
fmt.Println()
}
}
// PullFromFullNameList 根据镜像名列表拉取全部的镜像
func PullFromFullNameList(fullImageNameList []string) (errorPullImageList []string) {
for _, dep := range fullImageNameList {
pullResult := PullFromCmiiHarbor(dep)
if pullResult == nil {
errorPullImageList = append(errorPullImageList, dep)
continue
}
scanner := bufio.NewScanner(pullResult)
for scanner.Scan() {
line := scanner.Text()
if strings.Contains(line, "\"status\":\"Pulling from") {
fmt.Println(line)
}
if strings.Contains(line, "Status: Image is up to date for") {
fmt.Println(line)
}
}
fmt.Println()
}
return errorPullImageList
}
func PullFromListAndCompressSplit(fullImageNameList []string, gzipFolder string) (errorPullImageList, errorGzipImageList []string) {
errorPullImageList = PullFromFullNameList(fullImageNameList)
// generate a project folder
err := os.MkdirAll(gzipFolder, os.ModeDir)
if err != nil {
if !errors.Is(err, os.ErrExist) {
log.ErrorF("[ImagePullFromListAndCompressSplit] - create folder of %s error %s", gzipFolder, err.Error())
}
}
var tarGzipFileNameList []string
for _, image := range fullImageNameList {
if !SaveToTarGZ(image, gzipFolder) {
errorGzipImageList = append(errorGzipImageList, image)
continue
}
tarGzipFileNameList = append(tarGzipFileNameList, convertImageGzipFileName(image))
}
utils.BeautifulPrintListWithTitle(tarGzipFileNameList, "image gzip name list")
return errorPullImageList, errorGzipImageList
}
func LoadFromGzipFilePath(gzipFullPath string) bool {
openFile, err := os.OpenFile(gzipFullPath, 0, fs.ModePerm)
if err != nil {
log.ErrorF("[ImageLoadFromFile] - failed to open file %s, error is %s", gzipFullPath, err.Error())
return false
}
loadResponse, err := apiClient.ImageLoad(context.TODO(), openFile, true)
if err != nil {
log.ErrorF("[ImageLoadFromFile] - load error %s, error is %s", gzipFullPath, err.Error())
return false
}
log.InfoF("[ImageLoadFromFile] - load of %s, result is %s", gzipFullPath, strconv.FormatBool(loadResponse.JSON))
scanner := bufio.NewScanner(loadResponse.Body)
for scanner.Scan() {
line := scanner.Text()
fmt.Println(line)
}
return true
}
func LoadFromFolderPath(folderPath string) (errorLoadImageNameList []string) {
if !strings.HasSuffix(folderPath, "/") {
folderPath += "/"
}
dirEntries, err := os.ReadDir(folderPath)
if err != nil {
log.ErrorF("[ImageLoadFromFolderPath] - error read folder %s error is %s", folderPath, err.Error())
return
}
// load gzip file
for _, dirEntry := range dirEntries {
if strings.HasSuffix(dirEntry.Name(), ".tar.gz") {
if !LoadFromGzipFilePath(folderPath + dirEntry.Name()) {
errorLoadImageNameList = append(errorLoadImageNameList, folderPath+dirEntry.Name())
}
}
}
return errorLoadImageNameList
}
func SaveToTarGZ(targetImageName, folderPathPrefix string) bool {
imageGetByName := GetByName(targetImageName)
if imageGetByName == nil {
log.ErrorF("[ImageSaveToTarGZ] - %s not exits", targetImageName)
return false
}
imageSaveTarStream, err := apiClient.ImageSave(context.TODO(), imageGetByName.RepoTags)
if err != nil {
log.ErrorF("[ImageSaveToTarGZ] - image save error %s", err.Error())
return false
}
var realImageTag string
for _, repoTag := range imageGetByName.RepoTags {
if !strings.Contains(repoTag, "8033") {
realImageTag = repoTag
break
}
}
gzipImageFile := convertImageGzipFileName(realImageTag)
if !strings.HasSuffix(folderPathPrefix, "/") {
folderPathPrefix += "/"
}
_ = os.MkdirAll(folderPathPrefix, os.ModeDir)
gzipImageFile = folderPathPrefix + gzipImageFile
log.InfoF("[ImageSaveToTarGZ] - start to save [%s] to [%s]", realImageTag, gzipImageFile)
_ = os.Remove(gzipImageFile)
tarFile, err := os.Create(gzipImageFile)
if err != nil {
log.ErrorF("[ImageSaveToTarGZ] - error create gzip %s file ! => %s ", gzipImageFile, err.Error())
return false
}
defer tarFile.Close()
// 创建pgzip writer
gw, err := pgzip.NewWriterLevel(tarFile, pgzip.DefaultCompression) // 你可以调整压缩级别
if err != nil {
log.ErrorF("[ImageSaveToTarGZ] - pgzip create writer error: %s", err.Error())
}
defer gw.Close()
// Copy the tar archive to the gzip writer.
if _, err := io.Copy(gw, imageSaveTarStream); err != nil {
log.ErrorF("[ImageSaveToTarGZ] - failed to copy tar archive to gzip writer: %s", err.Error())
return false
}
return true
}
// convertImageGzipFileName 必须输出长度为4的内容 =出现得次数为3
func convertImageGzipFileName(imageRepoTag string) (gzipFileName string) {
// harbor.cdcyy.cn/cmii/cmii-uav-platform:5.4.0 ==> cmlc=cmii=cmii-uav-platform=5.4.0.tar.gz
// rancher/fleet:v0.3.4
// ossr/srs:v5.0.1 ==> docker=cmii=srs=v5.0.1.tar.gz
// nginx:latest
// bitnami/minio:2022.5.4
// simonrupf/chronyd:0.4.3
// 10.1.1.1:8033/cmii/ok:1.2 不支持 不允许存在
split := strings.Split(imageRepoTag, ":")
//log.DebugF(" %s to %s", imageRepoTag, split)
if len(split) == 1 {
// nginx
return "docker=library=" + imageRepoTag + "=latest.tar.gz"
}
first := strings.Split(split[0], "/")
//log.DebugF(" split[0] %s to %s", split[0], first)
if len(first) == 3 {
// harbor.cdcyy.cn/cmii/cmii-uav-platform:5.4.0
// docker.io/ossr/srs:v5.0.1
if strings.HasPrefix(split[0], CmiiHarborPrefix) {
gzipFileName += "cmlc=cmii="
} else {
gzipFileName += "docker=cmii="
}
gzipFileName += first[2]
gzipFileName += "="
} else if len(first) == 4 {
// harbor.cdcyy.cn/cmii/ossr/srs:v5.0.1
if !strings.HasPrefix(split[0], CmiiHarborPrefix) {
return imageRepoTag
}
gzipFileName += "cmlc=cmii="
gzipFileName += first[3]
gzipFileName += "="
} else if len(first) == 2 {
// bitnami/redis
// ossrs/srs
gzipFileName += "docker="
gzipFileName += first[0]
gzipFileName += "="
gzipFileName += first[1]
gzipFileName += "="
} else if len(first) == 1 {
// nginx:latest
return "docker=library=" + split[0] + "=" + split[1] + ".tar.gz"
}
gzipFileName += split[1]
gzipFileName += ".tar.gz"
return gzipFileName
}
func ConvertCMiiImageMapToList(cmiiImageVersionMap map[string]string) (fullImageNameList []string) {
for image, tag := range cmiiImageVersionMap {
s := CmiiHarborPrefix + image + ":" + tag
fullImageNameList = append(fullImageNameList, s)
}
return fullImageNameList
}
func loginToDockerHub(HarborFullHost string) {
if HarborFullHost == "" {
HarborFullHost = "https://registry-1.docker.io"
}
login, err := apiClient.RegistryLogin(context.TODO(), types.AuthConfig{
Username: "icederce",
Password: "loveff.cxc.23",
Auth: "aWNlZGVyY2U6bG92ZWZmLmN4Yy4yMw==",
ServerAddress: HarborFullHost,
})
if err != nil {
log.ErrorF("[loginToDockerHub] - login to %s failed !", HarborFullHost)
}
log.DebugF("[loginToDockerHub] - login is %s", login.Status)
}
func WriteDependencyImageToFile() {
imageFilePrefix := "C:\\Users\\wddsh\\Documents\\IdeaProjects\\ProjectOctopus\\cmii_operator\\image\\"
middleFile := imageFilePrefix + "middle-image.txt"
_ = os.Remove(middleFile)
for _, image := range MiddlewareAmd64 {
utils.AppendContentToFile(image+"\n", middleFile)
}
rkeFile := imageFilePrefix + "rke-image.txt"
_ = os.Remove(rkeFile)
for _, image := range Rancher1204Amd64 {
utils.AppendContentToFile(image+"\n", rkeFile)
}
}

View File

@@ -0,0 +1,188 @@
package image
import (
"bufio"
"fmt"
"strconv"
"strings"
"testing"
"time"
"wdd.io/agent-common/assert"
"wdd.io/agent-common/utils"
)
func TestGetRunningContainer(t *testing.T) {
allContainer := GetRunningContainer()
for _, container := range allContainer {
utils.BeautifulPrint(container)
}
}
func TestGetAllContainer(t *testing.T) {
allContainer := GetAllContainer()
for _, container := range allContainer {
utils.BeautifulPrint(container)
}
}
func TestListService(t *testing.T) {
ListService()
}
func TestImageGetAll(t *testing.T) {
imageGetAll := GetAll()
for _, summary := range imageGetAll {
utils.BeautifulPrint(summary)
}
}
func TestImageGetByName(t *testing.T) {
image := "harbor.cdcyy.com.cn/cmii/cmii-uav-gateway:4.1.6-beta"
imageGetByName := GetByName(image)
utils.BeautifulPrint(imageGetByName)
}
func TestImageDelete(t *testing.T) {
image := "harbor.cdcyy.com.cn/cmii/cmii-uav-gateway:4.1.6-beta"
imageDelete := Delete(image)
for _, item := range imageDelete {
utils.BeautifulPrint(item)
}
}
func TestImagePullFromCmiiHarbor(t *testing.T) {
image := "harbor.cdcyy.com.cn/cmii/cmii-uav-gateway:4.1.6-beta"
pullFromCmiiHarbor := PullFromCmiiHarbor(image)
defer pullFromCmiiHarbor.Close()
scanner := bufio.NewScanner(pullFromCmiiHarbor)
for scanner.Scan() {
line := scanner.Text()
if strings.Contains(line, "\"status\":\"Pulling from") {
fmt.Println(line)
}
if strings.Contains(line, "Status: Image is up to date for") {
fmt.Println(line)
}
}
//var fs uintptr
//
//tools.DisplayJSONMessagesStream(pullFromCmiiHarbor, os.Stdout, fs, true, func(message tools.JSONMessage) {
//
//})
}
func TestImagePushToOctopusKindHarbor(t *testing.T) {
// re-tag
image := "harbor.cdcyy.com.cn/cmii/cmii-uav-gateway:4.1.6-beta"
newTag := "10.250.0.100:8033/cmii/cmii-uav-gateway:4.1.6-beta"
target := TagFromSourceToTarget(image, newTag)
assert.Equal(t, target, true, "image re-tag error !")
// push
pushResult := PushToOctopusKindHarbor(newTag)
defer pushResult.Close()
scanner := bufio.NewScanner(pushResult)
for scanner.Scan() {
}
fmt.Println("image push success!")
}
func TestImageLoadFromFile(t *testing.T) {
loadFromFile := LoadFromGzipFilePath("/root/octopus_image/cqga/cqga/cmlc=cmii=cmii-uav-user=5.2.0.tar.gz")
assert.Equal(t, loadFromFile, true, "image load error !")
}
func TestImageSaveToTarGZ(t *testing.T) {
image := "harbor.cdcyy.com.cn/cmii/cmii-uav-gateway:4.1.6-beta"
imageSaveToTarGZ := SaveToTarGZ(image, "/home/wdd/IdeaProjects/ProjectOctopus/cmii_operator/log")
assert.Equal(t, imageSaveToTarGZ, true, "image save to tar gz file error !")
}
func TestConvertImageGzipFileName(t *testing.T) {
test := []string{
"bitnami/redis:6.2.6-debian-10-r0",
"simonrupf/chronyd:0.4.3",
"harbor.cdcyy.com.cn/cmii/cmii-rtsp-operator:v4.1.0",
"harbor.cdcyy.com.cn/cmii/ossrs/srs:v4.0.136",
"ossrs/srs:v4.0.136",
"mongo:5.0",
"bitnami/minio:2023.5.4",
"busybox:latest",
"busybox",
}
for _, s := range test {
gzipFileName := convertImageGzipFileName(s)
fmt.Printf(" %s to %s \n", s, gzipFileName)
}
}
func TestImagePruneAllCmiiImages(t *testing.T) {
errorRemoveImageNameList := PruneAllCmiiImages()
utils.BeautifulPrintListWithTitle(errorRemoveImageNameList, "CMII Image Prune Error")
}
func TestImageTagFromSourceToTarget(t *testing.T) {
sourceImageName := "ossrs/srs:v5.0.195"
targetImageName := "harbor.wdd.io:8033/cmii/srs:v5.0.195"
if TagFromSourceToTarget(sourceImageName, targetImageName) {
pushResult := PushToOctopusKindHarbor(targetImageName)
defer pushResult.Close()
scanner := bufio.NewScanner(pushResult)
for scanner.Scan() {
}
}
}
func fibonacci(c, quit chan int64) {
x, y := int64(0), int64(1)
for {
select {
case c <- x:
x, y = y, x+y
fmt.Println("count is " + strconv.FormatInt(int64(<-c), 10))
case <-quit:
fmt.Println("quit current x is " + strconv.FormatInt(int64(x), 10))
return
}
}
}
func TestWriteDependencyImageToFile(t *testing.T) {
//WriteDependencyImageToFile()
c := make(chan int64, 1)
quit := make(chan int64, 1)
go fibonacci(c, quit)
after := time.After(time.Second)
<-after
quit <- 1
}

View File

@@ -0,0 +1,15 @@
#!/bin/bash
#for image in $(ls /root/octopus_image/rke)
#do
# echo "start to upload => $image"
# mc cp /root/octopus_image/rke/$image demo/cmlc-installation/rke-image-amd64/
# echo ""
#done
export local_path=/root/octopus_image/5.4.0
for image in $(ls $local_path); do
echo "start to upload => $image"
mc cp $local_path/$image demo/cmlc-installation/5.4.0/
echo ""
done

View File

@@ -0,0 +1,25 @@
bitnami/redis:6.2.6-debian-10-r0
bitnami/redis:6.2.14-debian-11-r1
bitnami/mysql:8.0.35-debian-11-r1
bitnami/mysql:8.1.0-debian-11-r42
simonrupf/chronyd:0.4.3
bitnami/bitnami-shell:10-debian-10-r140
bitnami/bitnami-shell:11-debian-11-r136
bitnami/rabbitmq:3.9.12-debian-10-r3
bitnami/rabbitmq:3.11.26-debian-11-r2
ossrs/srs:v4.0.136
ossrs/srs:v5.0.195
emqx/emqx:4.2.12
nacos/nacos-server:v2.1.2
nacos/nacos-server:v2.1.2-slim
mongo:5.0
rabbitmq:3.9-management
bitnami/minio:2022.5.4
bitnami/minio:2023.5.4
kubernetesui/dashboard:v2.0.1
kubernetesui/metrics-scraper:v1.0.4
ossrs/srs:v4.0-r3
nginx:1.21.3
redis:6.0.20-alpine
dyrnq/nfs-subdir-external-provisioner:v4.0.2
busybox:latest

View File

@@ -0,0 +1,185 @@
#!/bin/bash
cmii_image_list=(
cmlc=cmii=cmii-admin-data=5.4.0.tar.gz
cmlc=cmii=cmii-admin-gateway=5.4.0.tar.gz
docker=ossrs=srs=v4.0.136.tar.gz
)
middle_image_list=(
docker=bitnami=bitnami-shell=10-debian-10-r140.tar.gz
docker=kubernetesui=dashboard=v2.0.1.tar.gz
docker=bitnami=bitnami-shell=11-debian-11-r136.tar.gz
docker=kubernetesui=metrics-scraper=v1.0.4.tar.gz
docker=bitnami=minio=2022.5.4.tar.gz
docker=library=busybox=latest.tar.gz
docker=bitnami=minio=2023.5.4.tar.gz
docker=library=mongo=5.0.tar.gz
docker=bitnami=mysql=8.0.35-debian-11-r1.tar.gz
docker=library=nginx=1.21.3.tar.gz
docker=bitnami=mysql=8.1.0-debian-11-r42.tar.gz
docker=library=rabbitmq=3.9-management.tar.gz
docker=bitnami=rabbitmq=3.11.26-debian-11-r2.tar.gz
docker=library=redis=6.0.20-alpine.tar.gz
docker=bitnami=rabbitmq=3.9.12-debian-10-r3.tar.gz
docker=nacos=nacos-server=v2.1.2-slim.tar.gz
docker=bitnami=redis=6.2.14-debian-11-r1.tar.gz
docker=ossrs=srs=v4.0.136.tar.gz
docker=bitnami=redis=6.2.6-debian-10-r0.tar.gz
docker=ossrs=srs=v4.0-r3.tar.gz
docker=dyrnq=nfs-subdir-external-provisioner=v4.0.2.tar.gz
docker=ossrs=srs=v5.0.195.tar.gz
docker=emqx=emqx=4.2.12.tar.gz
docker=simonrupf=chronyd=0.4.3.tar.gz
)
rke_image_list=(
docker=rancher=backup-restore-operator=v1.0.3.tar.gz
docker=rancher=calico-cni=v3.17.2.tar.gz
docker=rancher=calico-ctl=v3.17.2.tar.gz
docker=rancher=calico-kube-controllers=v3.17.2.tar.gz
docker=rancher=calico-node=v3.17.2.tar.gz
docker=rancher=calico-pod2daemon-flexvol=v3.17.2.tar.gz
docker=rancher=cis-operator=v1.0.3.tar.gz
docker=rancher=cluster-proportional-autoscaler=1.7.1.tar.gz
docker=rancher=cluster-proportional-autoscaler=1.8.1.tar.gz
docker=rancher=configmap-reload=v0.3.0-rancher4.tar.gz
docker=rancher=coredns-coredns=1.8.0.tar.gz
docker=rancher=coreos-etcd=v3.4.14-rancher1.tar.gz
docker=rancher=coreos-flannel=v0.13.0-rancher1.tar.gz
docker=rancher=coreos-kube-state-metrics=v1.9.7.tar.gz
docker=rancher=coreos-prometheus-config-reloader=v0.39.0.tar.gz
docker=rancher=coreos-prometheus-operator=v0.39.0.tar.gz
docker=rancher=externalip-webhook=v0.1.6.tar.gz
docker=rancher=flannel-cni=v0.3.0-rancher6.tar.gz
docker=rancher=fleet-agent=v0.3.4.tar.gz
docker=rancher=fleet=v0.3.4.tar.gz
docker=rancher=fluentd=v0.1.24.tar.gz
docker=rancher=grafana-grafana=7.1.5.tar.gz
docker=rancher=hyperkube=v1.20.4-rancher1.tar.gz
docker=rancher=istio-kubectl=1.5.10.tar.gz
docker=rancher=jimmidyson-configmap-reload=v0.3.0.tar.gz
docker=rancher=k8s-dns-dnsmasq-nanny=1.15.2.tar.gz
docker=rancher=k8s-dns-kube-dns=1.15.2.tar.gz
docker=rancher=k8s-dns-node-cache=1.15.13.tar.gz
docker=rancher=k8s-dns-sidecar=1.15.2.tar.gz
docker=rancher=klipper-lb=v0.1.2.tar.gz
docker=rancher=kube-api-auth=v0.1.4.tar.gz
docker=rancher=kubernetes-external-dns=v0.7.3.tar.gz
docker=rancher=library-busybox=1.31.1.tar.gz
docker=rancher=library-busybox=1.32.1.tar.gz
docker=rancher=library-nginx=1.19.2-alpine.tar.gz
docker=rancher=library-traefik=1.7.19.tar.gz
docker=rancher=local-path-provisioner=v0.0.11.tar.gz
docker=rancher=local-path-provisioner=v0.0.14.tar.gz
docker=rancher=local-path-provisioner=v0.0.19.tar.gz
docker=rancher=log-aggregator=v0.1.7.tar.gz
docker=rancher=metrics-server=v0.4.1.tar.gz
docker=rancher=nginx-ingress-controller-defaultbackend=1.5-rancher1.tar.gz
docker=rancher=nginx-ingress-controller=nginx-0.43.0-rancher1.tar.gz
docker=rancher=opa-gatekeeper=v3.1.0-beta.7.tar.gz
docker=rancher=openzipkin-zipkin=2.14.2.tar.gz
docker=rancher=pause=3.2.tar.gz
docker=rancher=plugins-docker=18.09.tar.gz
docker=rancher=prom-alertmanager=v0.21.0.tar.gz
docker=rancher=prometheus-auth=v0.2.1.tar.gz
docker=rancher=prom-node-exporter=v1.0.1.tar.gz
docker=rancher=prom-prometheus=v2.18.2.tar.gz
docker=rancher=rancher-agent=v2.5.7.tar.gz
docker=rancher=rancher=v2.5.7.tar.gz
docker=rancher=rancher-webhook=v0.1.0-beta9.tar.gz
docker=rancher=rke-tools=v0.1.72.tar.gz
docker=rancher=security-scan=v0.1.14.tar.gz
docker=rancher=security-scan=v0.2.2.tar.gz
docker=rancher=shell=v0.1.6.tar.gz
docker=rancher=sonobuoy-sonobuoy=v0.16.3.tar.gz
docker=rancher=system-upgrade-controller=v0.6.2.tar.gz
)
oss_prefix=https://oss.demo.uavcmlc.com/cmlc-installation/shls
oss_middle_prefix=https://oss.demo.uavcmlc.com/cmlc-installation/mid-image-amd64
oss_rke_prefix=https://oss.demo.uavcmlc.com/cmlc-installation/rke-image-amd64
target_harbor_host=103.0.180.181:8033
cmii_image_download_from_oss() {
for image in "${cmii_image_list[@]}"; do
echo "start to download => $image"
curl -x socks5h://103.0.180.82:9997 $oss_prefix/$image -o $image
echo ""
done
}
middle_image_download_from_oss() {
mkdir -p /wdd/image/middle/
for image in "${middle_image_list[@]}"; do
echo "start to download => $image"
curl -x socks5h://103.0.180.82:9997 $oss_middle_prefix/$image -o /wdd/image/middle/$image
echo ""
done
}
rke_image_download_from_oss() {
mkdir -p /wdd/image/rke/
for image in "${rke_image_list[@]}"; do
echo "start to download => $image"
curl -x socks5h://103.0.180.82:9997 $oss_rke_prefix/$image -o /wdd/image/rke/$image
echo ""
done
}
image_load_to_harbor() {
local cmii_harbor_prefix="harbor.cdcyy.com.cn/cmii/"
for image in "${cmii_image_list[@]}"; do
echo "start to load => $image"
docker load <"$image"
echo ""
if [[ $image == cmlc* ]]; then
local app_name=$(echo $image | cut -d "=" -f3)
local ccc=$(echo $image | cut -d "=" -f4)
local app_tag="${ccc%.tar.gz}"
echo "from $cmii_harbor_prefix$app_name:$app_tag ==> $target_harbor_host/cmii/$app_name:$app_tag"
docker tag "$cmii_harbor_prefix$app_name:$app_tag" "$target_harbor_host/cmii/$app_name:$app_tag"
echo "start to push => $target_harbor_host/cmii/$app_name:$app_tag"
docker login -u admin -p V2ryStr@ngPss $target_harbor_host
docker push "$target_harbor_host/cmii/$app_name:$app_tag"
echo ""
fi
echo ""
done
for image in "${rke_image_list[@]}"; do
echo "start to load => $image"
docker load <"$image"
echo ""
local app_name_prefix=$(echo $image | cut -d "=" -f2)
local app_name=$(echo $image | cut -d "=" -f3)
local ccc=$(echo $image | cut -d "=" -f4)
local app_tag="${ccc%.tar.gz}"
echo "from $app_name_prefix/$app_name:$app_tag ==> $target_harbor_host/rancher/$app_name:$app_tag"
docker tag "$app_name_prefix/$app_name:$app_tag" "$target_harbor_host/rancher/$app_name:$app_tag"
echo "start to push => $target_harbor_host/rancher/$app_name:$app_tag"
docker login -u admin -p V2ryStr@ngPss $target_harbor_host
docker push "$target_harbor_host/rancher/$app_name:$app_tag"
echo
done
for image in "${middle_image_list[@]}"; do
echo "start to load => $image"
docker load <"$image"
echo ""
# docker=bitnami=redis=6.2.14-debian-11-r1.tar.gz
local app_name_prefix=$(echo $image | cut -d "=" -f2)
local app_name=$(echo $image | cut -d "=" -f3)
local ccc=$(echo $image | cut -d "=" -f4)
local app_tag="${ccc%.tar.gz}"
echo "from $app_name_prefix/$app_name:$app_tag ==> $target_harbor_host/cmii/$app_name:$app_tag"
echo "start to push => $target_harbor_host/cmii/$app_name:$app_tag"
docker login -u admin -p V2ryStr@ngPss $target_harbor_host
docker push "$target_harbor_host/cmii/$app_name:$app_tag"
done
}
create_harbor_project() {
curl -X POST -u "admin:V2ryStr@ngPss" -H "authorization: Basic YWRtaW46VjJyeVN0ckBuZ1Bzcw==" -H "Content-Type: application/json" -d '{"project_name":"cmii","registry_id":null,"metadata":{"public":"true"},"storage_limit":-1}' http://$target_harbor_host/api/v2.0/projects
curl -X POST -u "admin:V2ryStr@ngPss" -H "authorization: Basic YWRtaW46VjJyeVN0ckBuZ1Bzcw==" -H "Content-Type: application/json" -d '{"project_name":"rancher","registry_id":null,"metadata":{"public":"true"},"storage_limit":-1}' http://$target_harbor_host/api/v2.0/projects
}

View File

@@ -0,0 +1,70 @@
#!/bin/bash
full_image_name_list=(
harbor.cdcyy.com.cn/cmii/cmii-uav-cloud-live:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-data-post-process:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-depotautoreturn:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-logger:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-mqtthandler:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-notice:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-admin-gateway:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-cms:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-material-warehouse:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-process:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-autowaypoint:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-brain:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-mission:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-oauth:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-airspace:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-suav-supervision:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-user:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-admin-user:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-emergency:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-kpi-monitor:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-waypoint:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-device:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-alarm:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-clusters:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-surveillance:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-threedsimulation:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-open-gateway:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-industrial-portfolio:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-tower:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-developer:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-app-release:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-gateway:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-integration:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-admin-data:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-armypeople:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-base:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-logistics:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-seniclive:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-visualization:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-cms-portal:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-multiterminal:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-security:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-media:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-oms:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-securityh5:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-share:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-suav-platform-supervision:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-ai-brain:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-emergency-rescue:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-splice:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-jiangsuwenlv:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-open:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-qinghaitourism:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-qingdao:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-mws:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-threedsimulation:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-suav-platform-supervisionh5:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-detection:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-uav-platform-hljtt:5.4.0
harbor.cdcyy.com.cn/cmii/cmii-live-operator:5.2.0
harbor.cdcyy.com.cn/cmii/cmii-srs-oss-adaptor:2023-SA
)
gzip_image_name_list=(
ossrs/srs:v5.0.195
)

View File

@@ -0,0 +1,62 @@
rancher/backup-restore-operator:v1.0.3
rancher/calico-cni:v3.17.2
rancher/calico-ctl:v3.17.2
rancher/calico-kube-controllers:v3.17.2
rancher/calico-node:v3.17.2
rancher/calico-pod2daemon-flexvol:v3.17.2
rancher/cis-operator:v1.0.3
rancher/cluster-proportional-autoscaler:1.7.1
rancher/coredns-coredns:1.8.0
rancher/coreos-etcd:v3.4.14-rancher1
rancher/coreos-kube-state-metrics:v1.9.7
rancher/coreos-prometheus-config-reloader:v0.39.0
rancher/coreos-prometheus-operator:v0.39.0
rancher/externalip-webhook:v0.1.6
rancher/flannel-cni:v0.3.0-rancher6
rancher/coreos-flannel:v0.13.0-rancher1
rancher/fleet-agent:v0.3.4
rancher/fleet:v0.3.4
rancher/fluentd:v0.1.24
rancher/grafana-grafana:7.1.5
rancher/hyperkube:v1.20.4-rancher1
rancher/jimmidyson-configmap-reload:v0.3.0
rancher/k8s-dns-dnsmasq-nanny:1.15.2
rancher/k8s-dns-kube-dns:1.15.2
rancher/k8s-dns-node-cache:1.15.13
rancher/k8s-dns-sidecar:1.15.2
rancher/klipper-lb:v0.1.2
rancher/kube-api-auth:v0.1.4
rancher/kubectl:v1.20.4
rancher/kubernetes-external-dns:v0.7.3
rancher/cluster-proportional-autoscaler:1.8.1
rancher/library-busybox:1.31.1
rancher/library-busybox:1.32.1
rancher/library-nginx:1.19.2-alpine
rancher/library-traefik:1.7.19
rancher/local-path-provisioner:v0.0.11
rancher/local-path-provisioner:v0.0.14
rancher/local-path-provisioner:v0.0.19
rancher/log-aggregator:v0.1.7
rancher/istio-kubectl:1.5.10
rancher/metrics-server:v0.4.1
rancher/configmap-reload:v0.3.0-rancher4
rancher/nginx-ingress-controller-defaultbackend:1.5-rancher1
rancher/nginx-ingress-controller:nginx-0.43.0-rancher1
rancher/opa-gatekeeper:v3.1.0-beta.7
rancher/openzipkin-zipkin:2.14.2
rancher/pause:3.2
rancher/plugins-docker:18.09
rancher/prom-alertmanager:v0.21.0
rancher/prom-node-exporter:v1.0.1
rancher/prom-prometheus:v2.18.2
rancher/prometheus-auth:v0.2.1
rancher/rancher-agent:v2.5.7
rancher/rancher-webhook:v0.1.0-beta9
rancher/rancher:v2.5.7
rancher/rke-tools:v0.1.72
jerrychina2020/rke-tools:v0.175-linux
rancher/security-scan:v0.1.14
rancher/security-scan:v0.2.2
rancher/shell:v0.1.6
rancher/sonobuoy-sonobuoy:v0.16.3
rancher/system-upgrade-controller:v0.6.2

View File

@@ -0,0 +1,119 @@
2024-01-10-14-54-51 uavcloud-demo cmii-uav-platform 5.2.0-011002 5.2.0-011003
2024-01-10-14-59-07 uavcloud-devflight cmii-uav-depotautoreturn 123sdsa45678 12345678
2024-01-10-15-09-29 uavcloud-demo cmii-uav-platform 5.2.0-011003 5.2.0-011004
2024-01-10-17-15-04 uavcloud-test cmii-suav-supervision 5.2.0-validation 5.2.0-011001
2024-01-11-11-06-10 uavcloud-demo cmii-uav-platform 5.2.0-011004 5.2.0-011101
2024-01-11-11-36-56 uavcloud-demo cmii-uav-waypoint 5.2.0 5.2.0-011101
2024-01-11-11-58-15 uavcloud-uavms uavms-lowaltitude-platform 5.1.0 5.2.0-011101
2024-01-11-14-00-34 uavcloud-uavms uavms-lowaltitude-platform 5.1.0-011102 5.1.0-011103
2024-01-11-14-49-53 uavcloud-demo cmii-uav-waypoint 5.2.0-011101 5.2.0-011102
2024-01-11-15-32-28 uavcloud-demo cmii-uav-platform 5.2.0-011101 5.2.0-011102
2024-01-11-17-09-44 uavcloud-feature cmii-uav-platform 5.2.0-validation 5.2.0-011102
2024-01-11-17-35-47 uavcloud-uavms cmii-uav-surveillance 5.1.0-LAIN05A 5.1.0-011101
2024-01-11-17-38-06 uavcloud-uavms uavms-lowaltitude-platform 5.1.0-011103 5.1.0-011102
2024-01-11-17-49-09 uavcloud-uavms uavms-lowaltitude-platform 5.1.0-011102 5.1.0-011104
2024-01-12-10-38-30 uavcloud-uavms uavms-lowaltitude-platform 5.1.0-011105 5.2.0-011201
2024-01-12-12-09-59 uavcloud-uavms uavms-lowaltitude-platform 5.2.0-011201 5.2.0-011202
2024-01-12-17-13-32 uavcloud-test cmii-suav-supervision 5.2.0-011001 5.2.0-011201
2024-01-12-17-22-47 uavcloud-demo cmii-uav-platform 5.2.0-011102 5.2.0-011201
2024-01-15-11-56-33 uavcloud-test cmii-suav-supervision 5.2.0-011201 5.2.0-011501
2024-01-16-10-22-02 uavcloud-test cmii-suav-supervision 5.2.0-011501 5.2.0-011601
2024-01-16-11-40-31 uavcloud-uavms uavms-lowaltitude-platform 5.2.0-011202 5.2.0-snapshot
2024-01-16-11-58-30 uavcloud-test cmii-suav-supervision 5.2.0-011601 5.2.0-011602
2024-01-16-13-55-32 uavcloud-test cmii-suav-supervision 5.2.0-011602 5.2.0-011603
2024-01-16-14-51-05 uavcloud-test cmii-suav-supervision 5.2.0-011603 5.2.0-011604
2024-01-17-16-13-39 uavcloud-test cmii-suav-supervision 5.2.0-011604 5.2.0-0117
2024-01-19-14-17-03 uavcloud-test cmii-suav-supervision 5.2.0-0117 5.2.0-011901
2024-02-23-09-31-21 uavcloud-demo cmii-uav-device 5.4.0 5.4.0-26906
2024-02-23-10-55-14 uavcloud-demo cmii-uav-device 5.4.0-26906 5.4.0-26906-01
2024-02-23-14-32-05 uavcloud-devflight cmii-uav-device 5.2.0-validation 5.4.0-26906-01
2024-02-28-17-09-55 uavcloud-demo cmii-uav-device 5.4.0 5.4.0-26905
2024-03-04-17-33-02 uavcloud-demo cmii-uav-platform 5.4.0-25263 5.4.0-hotfix
2024-03-08-12-02-18 zyga cmii-uav-oauth 8033/cmii/cmii-uav-oauth5.4.0
2024-03-08-12-02-19 zyga cmii-uav-user 8033/cmii/cmii-uav-user5.4.0
2024-03-08-12-02-21 zyga cmii-uav-cms 8033/cmii/cmii-uav-cms5.3.0
2024-03-08-12-02-22 zyga cmii-uav-industrial-portfolio 8033/cmii/cmii-uav-industrial-portfolio5.4.0-27348-1
2024-03-08-12-02-23 zyga cmii-uav-surveillance 8033/cmii/cmii-uav-surveillance5.4.0-25916
2024-03-08-12-02-24 zyga cmii-uav-mission 8033/cmii/cmii-uav-mission5.4.0-26462-0307
2024-03-08-12-02-26 zyga cmii-admin-gateway 8033/cmii/cmii-admin-gateway5.4.0
2024-03-08-12-02-27 zyga cmii-uav-alarm 8033/cmii/cmii-uav-alarm5.4.0
2024-03-08-12-02-28 zyga cmii-uav-emergency 8033/cmii/cmii-uav-emergency5.3.0
2024-03-08-12-02-30 zyga cmii-uav-material-warehouse 8033/cmii/cmii-uav-material-warehouse5.4.0
2024-03-08-12-02-31 zyga cmii-uav-airspace 8033/cmii/cmii-uav-airspace5.4.0
2024-03-08-12-02-33 zyga cmii-uav-brain 8033/cmii/cmii-uav-brain5.4.0
2024-03-08-12-02-34 zyga cmii-uav-process 8033/cmii/cmii-uav-process5.4.0
2024-03-08-12-02-36 zyga cmii-uav-notice 8033/cmii/cmii-uav-notice5.4.0
2024-03-08-12-02-37 zyga cmii-uav-waypoint 8033/cmii/cmii-uav-waypoint5.4.0-26768
2024-03-08-12-02-38 zyga cmii-uav-autowaypoint 8033/cmii/cmii-uav-autowaypoint4.1.6-cm
2024-03-08-12-02-40 zyga cmii-uav-data-post-process 8033/cmii/cmii-uav-data-post-process5.4.0
2024-03-08-12-02-41 zyga cmii-admin-data 8033/cmii/cmii-admin-data5.4.0
2024-03-08-12-02-42 zyga cmii-uav-cloud-live 8033/cmii/cmii-uav-cloud-live5.4.0
2024-03-08-12-02-43 zyga cmii-uav-gateway 8033/cmii/cmii-uav-gateway5.4.0
2024-03-08-12-02-45 zyga cmii-uav-logger 8033/cmii/cmii-uav-logger5.4.0
2024-03-08-12-02-46 zyga cmii-uav-mqtthandler 8033/cmii/cmii-uav-mqtthandler5.4.0-25916
2024-03-08-12-02-47 zyga cmii-admin-user 8033/cmii/cmii-admin-user5.4.0
2024-03-08-12-02-54 zyga cmii-suav-supervision 8033/cmii/cmii-suav-supervision5.2.0
2024-03-08-12-02-55 zyga cmii-uav-developer 8033/cmii/cmii-uav-developer5.4.0
2024-03-08-12-02-57 zyga cmii-uav-integration 8033/cmii/cmii-uav-integration5.4.0-25916
2024-03-08-12-02-58 zyga cmii-open-gateway 8033/cmii/cmii-open-gateway5.4.0
2024-03-08-12-02-59 zyga cmii-uav-device 8033/cmii/cmii-uav-device5.4.0-25916
2024-03-08-14-06-05 zyga cmii-uav-cloud-live 8033/cmii/cmii-uav-cloud-live5.4.0
2024-03-08-14-06-07 zyga cmii-uav-mqtthandler 8033/cmii/cmii-uav-mqtthandler5.4.0-25916
2024-03-08-14-11-26 zyga cmii-uav-industrial-portfolio 8033/cmii/cmii-uav-industrial-portfolio5.4.0-27348-1
2024-03-08-14-11-29 zyga cmii-open-gateway 8033/cmii/cmii-open-gateway5.4.0
2024-03-08-14-11-31 zyga cmii-uav-developer 8033/cmii/cmii-uav-developer5.4.0
2024-03-08-14-11-33 zyga cmii-admin-user 8033/cmii/cmii-admin-user5.4.0
2024-03-08-14-11-35 zyga cmii-uav-mqtthandler 8033/cmii/cmii-uav-mqtthandler5.4.0-25916
2024-03-08-14-11-37 zyga cmii-uav-user 8033/cmii/cmii-uav-user5.4.0
2024-03-08-14-11-40 zyga cmii-uav-airspace 8033/cmii/cmii-uav-airspace5.4.0
2024-03-08-14-11-42 zyga cmii-uav-logger 8033/cmii/cmii-uav-logger5.4.0
2024-03-08-14-11-44 zyga cmii-uav-process 8033/cmii/cmii-uav-process5.4.0
2024-03-08-14-11-48 zyga cmii-uav-notice 8033/cmii/cmii-uav-notice5.4.0
2024-03-08-14-11-55 zyga cmii-uav-surveillance 8033/cmii/cmii-uav-surveillance5.4.0-25916
2024-03-08-14-12-04 zyga cmii-uav-waypoint 8033/cmii/cmii-uav-waypoint5.4.0-26768
2024-03-08-14-12-13 zyga cmii-uav-brain 8033/cmii/cmii-uav-brain5.4.0
2024-03-08-14-12-20 zyga cmii-uav-cms 8033/cmii/cmii-uav-cms5.3.0
2024-03-08-14-12-22 zyga cmii-uav-material-warehouse 8033/cmii/cmii-uav-material-warehouse5.4.0
2024-03-08-14-12-24 zyga cmii-admin-gateway 8033/cmii/cmii-admin-gateway5.4.0
2024-03-08-14-12-26 zyga cmii-uav-emergency 8033/cmii/cmii-uav-emergency5.3.0
2024-03-08-14-12-28 zyga cmii-uav-gateway 8033/cmii/cmii-uav-gateway5.4.0
2024-03-08-14-12-31 zyga cmii-uav-integration 8033/cmii/cmii-uav-integration5.4.0-25916
2024-03-08-14-12-37 zyga cmii-admin-data 8033/cmii/cmii-admin-data5.4.0
2024-03-08-14-12-40 zyga cmii-suav-supervision 8033/cmii/cmii-suav-supervision5.2.0
2024-03-08-14-12-42 zyga cmii-uav-autowaypoint 8033/cmii/cmii-uav-autowaypoint4.1.6-cm
2024-03-08-14-12-44 zyga cmii-uav-cloud-live 8033/cmii/cmii-uav-cloud-live5.4.0
2024-03-08-14-12-46 zyga cmii-uav-mission 8033/cmii/cmii-uav-mission5.4.0-26462-0307
2024-03-08-14-12-48 zyga cmii-uav-oauth 8033/cmii/cmii-uav-oauth5.4.0
2024-03-08-14-12-50 zyga cmii-uav-alarm 8033/cmii/cmii-uav-alarm5.4.0
2024-03-08-14-12-53 zyga cmii-uav-data-post-process 8033/cmii/cmii-uav-data-post-process5.4.0
2024-03-08-14-12-55 zyga cmii-uav-device 8033/cmii/cmii-uav-device5.4.0-25916
2024-03-08-14-12-57 zyga cmii-uav-platform-cms-portal 8033/cmii/cmii-uav-platform-cms-portal5.4.0
2024-03-08-14-13-01 zyga cmii-uav-platform-detection 8033/cmii/cmii-uav-platform-detection5.4.0
2024-03-08-14-13-15 zyga cmii-uav-platform-emergency-rescue 8033/cmii/cmii-uav-platform-emergency-rescue5.2.0
2024-03-08-14-13-19 zyga cmii-uav-platform-media 8033/cmii/cmii-uav-platform-media5.4.0
2024-03-08-14-13-32 zyga cmii-uav-platform-open 8033/cmii/cmii-uav-platform-open5.4.0
2024-03-08-14-13-37 zyga cmii-uav-platform-splice 8033/cmii/cmii-uav-platform-splice5.4.0
2024-03-08-14-13-50 zyga cmii-uav-platform 8033/cmii/cmii-uav-platform5.4.0-25263
2024-03-08-14-13-54 zyga cmii-uav-platform-ai-brain 8033/cmii/cmii-uav-platform-ai-brain5.4.0
2024-03-08-14-14-08 zyga cmii-uav-platform-armypeople 8033/cmii/cmii-uav-platform-armypeople5.4.0
2024-03-08-14-14-12 zyga cmii-uav-platform-oms 8033/cmii/cmii-uav-platform-oms5.4.0
2024-03-08-14-14-26 zyga cmii-uav-platform-base 8033/cmii/cmii-uav-platform-base5.4.0
2024-03-08-14-14-30 zyga cmii-uav-platform-mws 8033/cmii/cmii-uav-platform-mws5.4.0
2024-03-08-14-14-44 zyga cmii-uav-platform-visualization 8033/cmii/cmii-uav-platform-visualization5.2.0
2024-03-08-14-14-48 zyga cmii-suav-platform-supervision 8033/cmii/cmii-suav-platform-supervision5.4.0
2024-03-08-14-15-01 zyga cmii-uav-platform-logistics 8033/cmii/cmii-uav-platform-logistics5.4.0
2024-03-08-14-15-06 zyga cmii-uav-platform-securityh5 8033/cmii/cmii-uav-platform-securityh55.4.0
2024-03-08-14-15-19 zyga cmii-suav-platform-supervisionh5 8033/cmii/cmii-suav-platform-supervisionh55.4.0
2024-03-08-14-15-23 zyga cmii-uav-platform-security 8033/cmii/cmii-uav-platform-security4.1.6
2024-03-08-14-15-37 zyga cmii-uav-platform-seniclive 8033/cmii/cmii-uav-platform-seniclive5.2.0
2024-03-08-14-15-41 zyga cmii-uav-platform-share 8033/cmii/cmii-uav-platform-share5.4.0
2024-03-08-14-15-55 zyga cmii-uav-platform-multiterminal 8033/cmii/cmii-uav-platform-multiterminal5.4.0
2024-03-08-15-16-14 uavcloud-demo cmii-uav-platform 5.4.0-25263 5.4.0
2024-03-11-11-20-15 zyga cmii-uav-surveillance 5.4.0 5.4.0-leaflet
2024-03-11-15-42-15 uavcloud-demo cmii-uav-platform 5.4.0 5.4.0-25263-0311
2024-03-19-17-37-53 uavcloud-demo cmii-uav-tower 5.4.0 5.4.0-0319
2024-03-19-17-39-21 uavcloud-demo cmii-uav-airspace 5.4.0 5.4.0-0319
2024-03-20-09-11-35 uavcloud-demo cmii-uav-mqtthandler 5.4.0-25916-1 5.4.0-25916-032001
2024-03-20-09-12-29 uavcloud-demo cmii-uav-industrial-portfolio 5.4.0-27348-2 5.4.0-27348-032001
2024-03-20-09-14-23 uavcloud-demo cmii-uav-platform 5.4.0-031901 5.4.0-25263-ai-032001
2024-03-20-09-21-51 uavcloud-demo cmii-uav-platform 5.4.0-25263-ai-032001 5.4.0-031901

5
agent-operator/main.go Normal file
View File

@@ -0,0 +1,5 @@
package agent_operator
func main() {
}

View File

@@ -0,0 +1,307 @@
package tools
import (
"encoding/json"
"fmt"
"io"
"strings"
"time"
units "github.com/docker/go-units"
"github.com/moby/term"
"github.com/morikuni/aec"
)
// RFC3339NanoFixed is time.RFC3339Nano with nanoseconds padded using zeros to
// ensure the formatted time isalways the same number of characters.
const RFC3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
// JSONError wraps a concrete Code and Message, Code is
// an integer error code, Message is the error message.
type JSONError struct {
Code int `json:"code,omitempty"`
Message string `json:"message,omitempty"`
}
func (e *JSONError) Error() string {
return e.Message
}
// JSONProgress describes a progress message in a JSON stream.
type JSONProgress struct {
// Current is the current status and value of the progress made towards Total.
Current int64 `json:"current,omitempty"`
// Total is the end value describing when we made 100% progress for an operation.
Total int64 `json:"total,omitempty"`
// Start is the initial value for the operation.
Start int64 `json:"start,omitempty"`
// HideCounts. if true, hides the progress count indicator (xB/yB).
HideCounts bool `json:"hidecounts,omitempty"`
// Units is the unit to print for progress. It defaults to "bytes" if empty.
Units string `json:"units,omitempty"`
// terminalFd is the fd of the current terminal, if any. It is used
// to get the terminal width.
terminalFd uintptr
// nowFunc is used to override the current time in tests.
nowFunc func() time.Time
// winSize is used to override the terminal width in tests.
winSize int
}
func (p *JSONProgress) String() string {
var (
width = p.width()
pbBox string
numbersBox string
timeLeftBox string
)
if p.Current <= 0 && p.Total <= 0 {
return ""
}
if p.Total <= 0 {
switch p.Units {
case "":
return fmt.Sprintf("%8v", units.HumanSize(float64(p.Current)))
default:
return fmt.Sprintf("%d %s", p.Current, p.Units)
}
}
percentage := int(float64(p.Current)/float64(p.Total)*100) / 2
if percentage > 50 {
percentage = 50
}
if width > 110 {
// this number can't be negative gh#7136
numSpaces := 0
if 50-percentage > 0 {
numSpaces = 50 - percentage
}
pbBox = fmt.Sprintf("[%s>%s] ", strings.Repeat("=", percentage), strings.Repeat(" ", numSpaces))
}
switch {
case p.HideCounts:
case p.Units == "": // no units, use bytes
current := units.HumanSize(float64(p.Current))
total := units.HumanSize(float64(p.Total))
numbersBox = fmt.Sprintf("%8v/%v", current, total)
if p.Current > p.Total {
// remove total display if the reported current is wonky.
numbersBox = fmt.Sprintf("%8v", current)
}
default:
numbersBox = fmt.Sprintf("%d/%d %s", p.Current, p.Total, p.Units)
if p.Current > p.Total {
// remove total display if the reported current is wonky.
numbersBox = fmt.Sprintf("%d %s", p.Current, p.Units)
}
}
if p.Current > 0 && p.Start > 0 && percentage < 50 {
fromStart := p.now().Sub(time.Unix(p.Start, 0))
perEntry := fromStart / time.Duration(p.Current)
left := time.Duration(p.Total-p.Current) * perEntry
left = (left / time.Second) * time.Second
if width > 50 {
timeLeftBox = " " + left.String()
}
}
return pbBox + numbersBox + timeLeftBox
}
// now returns the current time in UTC, but can be overridden in tests
// by setting JSONProgress.nowFunc to a custom function.
func (p *JSONProgress) now() time.Time {
if p.nowFunc != nil {
return p.nowFunc()
}
return time.Now().UTC()
}
// width returns the current terminal's width, but can be overridden
// in tests by setting JSONProgress.winSize to a non-zero value.
func (p *JSONProgress) width() int {
if p.winSize != 0 {
return p.winSize
}
ws, err := term.GetWinsize(p.terminalFd)
if err == nil {
return int(ws.Width)
}
return 200
}
// JSONMessage defines a message struct. It describes
// the created time, where it from, status, ID of the
// message. It's used for docker events.
type JSONMessage struct {
Stream string `json:"stream,omitempty"`
Status string `json:"status,omitempty"`
Progress *JSONProgress `json:"progressDetail,omitempty"`
ProgressMessage string `json:"progress,omitempty"` // deprecated
ID string `json:"id,omitempty"`
From string `json:"from,omitempty"`
Time int64 `json:"time,omitempty"`
TimeNano int64 `json:"timeNano,omitempty"`
Error *JSONError `json:"errorDetail,omitempty"`
ErrorMessage string `json:"error,omitempty"` // deprecated
// Aux contains out-of-band data, such as digests for push signing and image id after building.
Aux *json.RawMessage `json:"aux,omitempty"`
}
func clearLine(out io.Writer) {
eraseMode := aec.EraseModes.All
cl := aec.EraseLine(eraseMode)
fmt.Fprint(out, cl)
}
func cursorUp(out io.Writer, l uint) {
fmt.Fprint(out, aec.Up(l))
}
func cursorDown(out io.Writer, l uint) {
fmt.Fprint(out, aec.Down(l))
}
// Display prints the JSONMessage to out. If isTerminal is true, it erases
// the entire current line when displaying the progressbar. It returns an
// error if the [JSONMessage.Error] field is non-nil.
func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error {
if jm.Error != nil {
return jm.Error
}
var endl string
if isTerminal && jm.Stream == "" && jm.Progress != nil {
clearLine(out)
endl = "\r"
fmt.Fprint(out, endl)
} else if jm.Progress != nil && jm.Progress.String() != "" { // disable progressbar in non-terminal
return nil
}
if jm.TimeNano != 0 {
fmt.Fprintf(out, "%s ", time.Unix(0, jm.TimeNano).Format(RFC3339NanoFixed))
} else if jm.Time != 0 {
fmt.Fprintf(out, "%s ", time.Unix(jm.Time, 0).Format(RFC3339NanoFixed))
}
if jm.ID != "" {
fmt.Fprintf(out, "%s: ", jm.ID)
}
if jm.From != "" {
fmt.Fprintf(out, "(from %s) ", jm.From)
}
if jm.Progress != nil && isTerminal {
fmt.Fprintf(out, "%s %s%s", jm.Status, jm.Progress.String(), endl)
} else if jm.ProgressMessage != "" { // deprecated
fmt.Fprintf(out, "%s %s%s", jm.Status, jm.ProgressMessage, endl)
} else if jm.Stream != "" {
fmt.Fprintf(out, "%s%s", jm.Stream, endl)
} else {
fmt.Fprintf(out, "%s%s\n", jm.Status, endl)
}
return nil
}
// DisplayJSONMessagesStream reads a JSON message stream from in, and writes
// each [JSONMessage] to out. It returns an error if an invalid JSONMessage
// is received, or if a JSONMessage containers a non-zero [JSONMessage.Error].
//
// Presentation of the JSONMessage depends on whether a terminal is attached,
// and on the terminal width. Progress bars ([JSONProgress]) are suppressed
// on narrower terminals (< 110 characters).
//
// - isTerminal describes if out is a terminal, in which case it prints
// a newline ("\n") at the end of each line and moves the cursor while
// displaying.
// - terminalFd is the fd of the current terminal (if any), and used
// to get the terminal width.
// - auxCallback allows handling the [JSONMessage.Aux] field. It is
// called if a JSONMessage contains an Aux field, in which case
// DisplayJSONMessagesStream does not present the JSONMessage.
func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool, auxCallback func(JSONMessage)) error {
var (
dec = json.NewDecoder(in)
ids = make(map[string]uint)
)
for {
var diff uint
var jm JSONMessage
if err := dec.Decode(&jm); err != nil {
if err == io.EOF {
break
}
return err
}
if jm.Aux != nil {
if auxCallback != nil {
auxCallback(jm)
}
continue
}
if jm.Progress != nil {
jm.Progress.terminalFd = terminalFd
}
if jm.ID != "" && (jm.Progress != nil || jm.ProgressMessage != "") {
line, ok := ids[jm.ID]
if !ok {
// NOTE: This approach of using len(id) to
// figure out the number of lines of history
// only works as long as we clear the history
// when we output something that's not
// accounted for in the map, such as a line
// with no ID.
line = uint(len(ids))
ids[jm.ID] = line
if isTerminal {
fmt.Fprintf(out, "\n")
}
}
diff = uint(len(ids)) - line
if isTerminal {
cursorUp(out, diff)
}
} else {
// When outputting something that isn't progress
// output, clear the history of previous lines. We
// don't want progress entries from some previous
// operation to be updated (for example, pull -a
// with multiple tags).
ids = make(map[string]uint)
}
err := jm.Display(out, isTerminal)
if jm.ID != "" && isTerminal {
cursorDown(out, diff)
}
if err != nil {
return err
}
}
return nil
}
// Stream is an io.Writer for output with utilities to get the output's file
// descriptor and to detect wether it's a terminal.
//
// it is subset of the streams.Out type in
// https://pkg.go.dev/github.com/docker/cli@v20.10.17+incompatible/cli/streams#Out
type Stream interface {
io.Writer
FD() uintptr
IsTerminal() bool
}
// DisplayJSONMessagesToStream prints json messages to the output Stream. It is
// used by the Docker CLI to print JSONMessage streams.
func DisplayJSONMessagesToStream(in io.Reader, stream Stream, auxCallback func(JSONMessage)) error {
return DisplayJSONMessagesStream(in, stream, stream.FD(), stream.IsTerminal(), auxCallback)
}