Merge remote-tracking branch 'origin/local-ss' into local-ss

This commit is contained in:
zeaslity
2024-04-29 13:58:06 +08:00
43 changed files with 558 additions and 1129 deletions

View File

@@ -71,7 +71,7 @@ func (c *CmiiUpdateMessage) SendMessage() (message Message) {
var m Message var m Message
err = json.Unmarshal(bodyBytes, &m) err = json.Unmarshal(bodyBytes, &m)
if err != nil { if err != nil {
log.ErrorF("Error unmarshaling response body to JSON:", err) log.ErrorF("Error unmarshaling response body to JSON: %s", err.Error())
return message return message
} }

View File

@@ -1,6 +1,9 @@
package pusher package pusher
import "testing" import (
"testing"
"wdd.io/agent-common/utils"
)
func TestCmiiUpdateMessage_SendMessage(t *testing.T) { func TestCmiiUpdateMessage_SendMessage(t *testing.T) {
c := &CmiiUpdateMessage{ c := &CmiiUpdateMessage{
@@ -12,5 +15,7 @@ func TestCmiiUpdateMessage_SendMessage(t *testing.T) {
DeployStatus: false, DeployStatus: false,
} }
utils.BeautifulPrint(c)
c.SendMessage() c.SendMessage()
} }

View File

@@ -14,7 +14,6 @@ import (
"sync" "sync"
"time" "time"
image2 "wdd.io/agent-common/image" image2 "wdd.io/agent-common/image"
"wdd.io/agent-common/utils"
) )
var k8sConfigFilePath = "/root/wdd/kube_config_cluster.yml" var k8sConfigFilePath = "/root/wdd/kube_config_cluster.yml"
@@ -142,36 +141,51 @@ func K8sDeploymentUpdateTag(supreme, appName, newTag string) (bool, string) {
updateResultLog := "" updateResultLog := ""
containers := deployment.Spec.Template.Spec.Containers containers := deployment.Spec.Template.Spec.Containers
if len(containers) == 1 {
// only update this kind
container := containers[0]
oldName := container.Image // 只支持container的数量为1的形式
container := containers[0]
split := strings.Split(container.Image, ":") oldName := container.Image
if strings.HasPrefix(container.Image, image2.CmiiHarborPrefix) { split := strings.Split(container.Image, ":")
// harbor if strings.HasPrefix(container.Image, image2.CmiiHarborPrefix) {
container.Image = split[0] + ":" + newTag // harbor
} else if strings.Contains(container.Image, "8033") { container.Image = split[0] + ":" + newTag
// 192.168.6.6:8033/rancher/k8s-dns-sidecar:v1.0.2 } else if strings.Contains(container.Image, "8033") {
container.Image = split[0] + ":" + split[1] + ":" + newTag // 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]", deployment.Namespace, appName, oldName, container.Image)
// 更新Cmii BIZ_GROUP
tagVersion := newTag
if strings.Contains(newTag, "-") {
tagVersion = strings.Split(newTag, "-")[0]
}
envList := container.Env
for _, envVar := range envList {
if envVar.Name == "IMAGE_VERSION" {
envVar.Value = tagVersion
} }
if envVar.Name == "BIZ_CONFIG_GROUP" {
updateResultLog = fmt.Sprintf(" [%s] [%s] [%s] from [%s] to [%s]", utils.TimeSplitFormatString(), supreme, appName, oldName, container.Image) envVar.Value = tagVersion
log.Info(updateResultLog)
// re assign
deployment.Spec.Template.Spec.Containers[0] = container
// update
_, err := k8sClient.AppsV1().Deployments(deployment.Namespace).Update(context.TODO(), deployment, metav1.UpdateOptions{})
if err != nil {
log.ErrorF("[K8sDeploymentUpdateTag] - update [%s] [%s] from [%s] to [%s] error ! %s", supreme, appName, split[1], container.Image, err.Error())
return false, ""
} }
} else if len(containers) == 2 { if envVar.Name == "SYS_CONFIG_GROUP" {
log.ErrorF("[K8sDeploymentUpdateTag] - cant update app with 2 containers !") envVar.Value = tagVersion
return false, "" }
}
log.DebugF("[DeploymentUpdateTag] - update env IMAGE_VERSION to [%s]", tagVersion)
// 赋值回去 很关键
deployment.Spec.Template.Spec.Containers[0] = container
// update
_, err := k8sClient.AppsV1().Deployments(deployment.Namespace).Update(context.TODO(), deployment, metav1.UpdateOptions{})
if err != nil {
sprintf := fmt.Sprintf("[DeploymentUpdateTag] - update [%s] [%s] from [%s] to [%s] error ! %s", deployment.Namespace, appName, split[1], container.Image, err.Error())
log.Error(sprintf)
return false, sprintf
} }
return true, updateResultLog return true, updateResultLog

View File

@@ -0,0 +1,74 @@
package cmii
import (
"bytes"
"io.wdd.message_pusher/pusher"
"text/template"
)
type ImageSyncMessage struct {
ImageFullName string `json:"imageFullName"`
ProjectName string `json:"projectName"`
ProjectNameSpace string `json:"projectNameSpace"`
ProjectMasterIP string `json:"projectMasterIP"`
ProjectMasterTopicName string `json:"projectMasterTopicName"`
InnerWorkTopicName string `json:"innerWorkTopicName"`
CurrentProcedure string `json:"currentProcedure"`
IsSyncFinished bool `json:"isSyncFinished"`
}
const imageSyncTemplate = `
{{if .IsSyncFinished}}
镜像更新状态: 成功😍
{{- else }}
镜像更新状态: 失败👿👿👿
{{- end}}
当前步骤: {{.CurrentProcedure}}
更新镜像: {{.ImageFullName}}
项目名称: {{.ProjectName}}
项目空间: {{.ProjectNameSpace}}
项目MasterIP: {{.ProjectMasterIP}}
项目Master名称: {{.ProjectMasterTopicName}}
中转节点名称: {{.InnerWorkTopicName}}
`
const ImageSyncTopicName = "imageSync"
var ImageSyncPushOptions = []pusher.PublishOption{
pusher.WithTitle("镜像同步更新"),
pusher.WithPriority("3"),
}
func (d *ImageSyncMessage) ParseTemplate() bytes.Buffer {
// 解析模板
tmpl, err := template.New("imageSyncTemplate").Parse(imageSyncTemplate)
if err != nil {
panic(err)
}
// 应用数据并打印结果
var result bytes.Buffer
err = tmpl.Execute(&result, d)
if err != nil {
panic(err)
}
return result
}
// PublishMessage 使用默认的Client 发布更新的消息
func (d *ImageSyncMessage) PublishMessage() *pusher.Message {
parseTemplate := d.ParseTemplate()
pusher.DefaultPusherClient.ChangeTopicName(ImageSyncTopicName)
result, err := pusher.DefaultPusherClient.PublishDefault(parseTemplate, ImageSyncPushOptions)
if err != nil {
log.ErrorF("[ImageSyncMessage] - message push error %s", err.Error())
return result
}
return result
}

View File

@@ -45,6 +45,7 @@ func main() {
{ {
router.CMIIRouter(engine) router.CMIIRouter(engine)
router.OctopusRouter(engine) router.OctopusRouter(engine)
router.ImageSyncRouter(engine)
} }
engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

View File

@@ -68,6 +68,10 @@ func NewDefaultClient() *Client {
return New(defaultConfig) return New(defaultConfig)
} }
func (c *Client) ChangeTopicName(topicName string) {
c.config.DefaultTopic = topicName
}
func (c *Client) PublishDefault(message bytes.Buffer, options []PublishOption) (*Message, error) { func (c *Client) PublishDefault(message bytes.Buffer, options []PublishOption) (*Message, error) {
if c.config.DefaultTopic == "" { if c.config.DefaultTopic == "" {
return nil, errors.New("[PublishDefault] - topic empty") return nil, errors.New("[PublishDefault] - topic empty")
@@ -135,17 +139,17 @@ func (c *Client) expandTopicURL(topic string) (string, error) {
if !topicRegex.MatchString(topic) { if !topicRegex.MatchString(topic) {
return "", fmt.Errorf("invalid topic name: %s", topic) return "", fmt.Errorf("invalid topic name: %s", topic)
} }
return fmt.Sprintf("%s/%s", c.config.DefaultHost, topic), nil return fmt.Sprintf("%s/%s", c.config.Host, topic), nil
} }
func (c *Client) parseConfigToOption(options []PublishOption) []PublishOption { func (c *Client) parseConfigToOption(options []PublishOption) []PublishOption {
config := c.config config := c.config
if config.DefaultToken != "" { if config.Token != "" {
options = append(options, WithBearerAuth(config.DefaultToken)) options = append(options, WithBearerAuth(config.Token))
} else if config.DefaultUser != "" { } else if config.User != "" {
if *config.DefaultPassword != "" { if *config.Password != "" {
options = append(options, WithBasicAuth(config.DefaultUser, *config.DefaultPassword)) options = append(options, WithBasicAuth(config.User, *config.Password))
} else { } else {
log.ErrorF("[parseConfigToOption] - default password is empty!") log.ErrorF("[parseConfigToOption] - default password is empty!")
} }

View File

@@ -16,13 +16,13 @@ const (
// Config is the config struct for a Client // Config is the config struct for a Client
type Config struct { type Config struct {
DefaultHost string `yaml:"default-host"` Host string `yaml:"default-host"`
DefaultUser string `yaml:"default-user"` User string `yaml:"default-user"`
DefaultPassword *string `yaml:"default-password"` Password *string `yaml:"default-password"`
DefaultToken string `yaml:"default-token"` Token string `yaml:"default-token"`
DefaultCommand string `yaml:"default-command"` DefaultCommand string `yaml:"default-command"`
DefaultTopic string `yaml:"default-topic"` DefaultTopic string `yaml:"default-topic"`
Subscribe []Subscribe `yaml:"subscribe"` Subscribe []Subscribe `yaml:"subscribe"`
} }
// Subscribe is the struct for a Subscription within Config // Subscribe is the struct for a Subscription within Config
@@ -38,13 +38,13 @@ type Subscribe struct {
// NewDefaultConfig creates a new Config struct for a Client // NewDefaultConfig creates a new Config struct for a Client
func NewDefaultConfig() *Config { func NewDefaultConfig() *Config {
return &Config{ return &Config{
DefaultHost: DefaultBaseURL, Host: DefaultBaseURL,
DefaultUser: "", User: "",
DefaultPassword: nil, Password: nil,
DefaultToken: DefaultBaseToken, Token: DefaultBaseToken,
DefaultTopic: DefaultTopic, DefaultTopic: DefaultTopic,
DefaultCommand: "", DefaultCommand: "",
Subscribe: nil, Subscribe: nil,
} }
} }

View File

@@ -3,9 +3,12 @@ package router
import ( import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"io.wdd.message_pusher/cmii" "io.wdd.message_pusher/cmii"
"io.wdd.message_pusher/pusher"
"net/http" "net/http"
) )
const CmiiUpdateTopicName = "cmii"
func CMIIRouter(r *gin.Engine) { func CMIIRouter(r *gin.Engine) {
cmiiGroup := r.Group("/cmii") cmiiGroup := r.Group("/cmii")
@@ -37,6 +40,8 @@ func CmiiUpdate(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"}) c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
return return
} }
pusher.DefaultPusherClient.ChangeTopicName(CmiiUpdateTopicName)
// 处理请求 // 处理请求
upgradeMessage := messageBody.DefaultPushUpgradeMessage() upgradeMessage := messageBody.DefaultPushUpgradeMessage()

View File

@@ -0,0 +1,38 @@
package router
import (
"github.com/gin-gonic/gin"
"io.wdd.message_pusher/cmii"
"net/http"
)
func ImageSyncRouter(r *gin.Engine) {
octopusGroup := r.Group("/image")
{
octopusGroup.POST("/sync", ImageSync)
}
}
// ImageSync godoc
// @Summary 镜像同步消息
// @Schemes
// @Description response to cmii update notification
// @Tags ImageSync
// @Accept json
// @Produce json
// @Param body body cmii.ImageSyncMessage true "请求体"
// @Success 200 {object} pusher.Message
// @Router /image/sync [post]
func ImageSync(c *gin.Context) {
// 获取请求中的参数
var imageSyncMessage cmii.ImageSyncMessage
if err := c.ShouldBindJSON(&imageSyncMessage); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
return
}
// 处理请求
upgradeMessage := imageSyncMessage.PublishMessage()
// *pusher.Message
c.JSON(http.StatusOK, upgradeMessage)
}

View File

@@ -40,7 +40,17 @@ public enum ImageFunctionEnum {
UPDATE_IMAGE_TAG( UPDATE_IMAGE_TAG(
"UPDATE_IMAGE_TAG", "UPDATE_IMAGE_TAG",
"关闭防火墙" "关闭防火墙"
),
FINISHED(
"FINISHED",
"同步更新完成"
); );
/**
* 函数名
*/
String funcName; String funcName;
String desc; String desc;

View File

@@ -1,5 +1,6 @@
package io.wdd.func.auto.beans; package io.wdd.func.auto.beans;
import io.wdd.pusher.beans.ImageSyncMessage;
import io.wdd.server.beans.po.ProjectInfoPO; import io.wdd.server.beans.po.ProjectInfoPO;
import io.wdd.server.beans.po.ServerInfoPO; import io.wdd.server.beans.po.ServerInfoPO;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@@ -32,4 +33,7 @@ public class ImageSyncContext {
// 我方的 机器 默认值为 192.168.35.71 // 我方的 机器 默认值为 192.168.35.71
String innerWorkerAgentName; String innerWorkerAgentName;
// 消息同步结构体
ImageSyncMessage imageSyncMessage;
} }

View File

@@ -1,6 +1,10 @@
package io.wdd.func.auto.service; package io.wdd.func.auto.service;
import io.wdd.func.auto.beans.ImageSyncContext; import io.wdd.func.auto.beans.ImageSyncContext;
import io.wdd.pusher.MessagePusher;
import io.wdd.pusher.beans.ImageSyncMessage;
import io.wdd.pusher.beans.NtfyReceiveMessage;
import io.wdd.pusher.beans.PushMessageType;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -22,6 +26,9 @@ public class ImageFuncScheduler {
@Resource @Resource
FuncService funcService; FuncService funcService;
@Resource
MessagePusher messagePusher;
public boolean runProcedure(ImageSyncContext imageSyncContext) { public boolean runProcedure(ImageSyncContext imageSyncContext) {
// before run // before run
@@ -55,16 +62,21 @@ public class ImageFuncScheduler {
arrayList.add(imageSyncContext.getProjectInfoPO().getProjectNamespace());//namespace arrayList.add(imageSyncContext.getProjectInfoPO().getProjectNamespace());//namespace
arrayList.add("");//targetImageFullName arrayList.add("");//targetImageFullName
imageSyncContext.setImageSyncFuncArgs(arrayList); imageSyncContext.setImageSyncFuncArgs(arrayList);
// 构建消息发送结构体
imageSyncContext.setImageSyncMessage(new ImageSyncMessage());
log.debug("beforeRunProcedure complete!"); log.debug("beforeRunProcedure complete!");
} }
private void afterRunProcedure(ImageSyncContext imageSyncContext) { private void afterRunProcedure(ImageSyncContext imageSyncContext) {
// message-pusher // message-pusher
ImageSyncMessage imageSyncMessage = imageSyncContext.getImageSyncMessage();
NtfyReceiveMessage receiveMessage = messagePusher.Send(imageSyncMessage, PushMessageType.IMAGE_SYNC);
log.info("Image sync message push result => {}", receiveMessage.getRaw());
// 检查是否安装完成, 对安装环境进行判定 // 检查是否安装完成, 对安装环境进行判定
log.debug("afterRunProcedure complete!"); log.debug("afterRunProcedure complete!");
@@ -98,6 +110,7 @@ public class ImageFuncScheduler {
log.info("prepare to update {} {} \n{}", imageSyncContext.getProjectInfoPO().getProjectNamespace(), imageSyncContext.getProjectMasterNode().getServerIpInV4(), realFullNameList); log.info("prepare to update {} {} \n{}", imageSyncContext.getProjectInfoPO().getProjectNamespace(), imageSyncContext.getProjectMasterNode().getServerIpInV4(), realFullNameList);
String innerWorkerAgentName = imageSyncContext.getInnerWorkerAgentName(); String innerWorkerAgentName = imageSyncContext.getInnerWorkerAgentName();
Assert.notNull(innerWorkerAgentName, "inner worker agent name cant not be null !"); Assert.notNull(innerWorkerAgentName, "inner worker agent name cant not be null !");
@@ -105,17 +118,30 @@ public class ImageFuncScheduler {
String outsideAgentTopicName = imageSyncContext.getProjectMasterNode().getTopicName(); String outsideAgentTopicName = imageSyncContext.getProjectMasterNode().getTopicName();
// 设置消息体
ImageSyncMessage imageSyncMessage = imageSyncContext.getImageSyncMessage();
imageSyncMessage.setIsSyncFinished(Boolean.FALSE);
imageSyncMessage.setProjectNameSpace(imageSyncContext.getProjectInfoPO().getProjectNamespace());
imageSyncMessage.setProjectName(imageSyncContext.getProjectInfoPO().getProjectName());
imageSyncMessage.setInnerWorkTopicName(imageSyncContext.getInnerWorkerAgentName());
imageSyncMessage.setProjectMasterTopicName(imageSyncContext.getProjectMasterNode().getTopicName());
imageSyncMessage.setProjectMasterIP(imageSyncContext.getProjectMasterNode().getServerIpInV4());
// //
List<String> resultLog; List<String> resultLog;
for (String fullName : realFullNameList) { for (String imageFullName : realFullNameList) {
imageSyncMessage.setImageFullName(imageFullName);
// innerWorkerAgent // innerWorkerAgent
imageSyncFuncArgs.set(0, fullName); imageSyncFuncArgs.set(0, imageFullName);
resultLog = funcService.callImageFuncService(innerWorkerAgentName, DOWNLOAD_DOCKER_IMAGE, imageSyncFuncArgs); resultLog = funcService.callImageFuncService(innerWorkerAgentName, DOWNLOAD_DOCKER_IMAGE, imageSyncFuncArgs);
if (!JudgeSyncBaseCommandResult(resultLog)) { if (!JudgeSyncBaseCommandResult(resultLog)) {
imageSyncMessage.setCurrentProcedure(DOWNLOAD_DOCKER_IMAGE.getFuncName());
return; return;
} }
resultLog = funcService.callImageFuncService(innerWorkerAgentName, COMPRESS_IMAGE_TO_GZIP, imageSyncFuncArgs); resultLog = funcService.callImageFuncService(innerWorkerAgentName, COMPRESS_IMAGE_TO_GZIP, imageSyncFuncArgs);
if (!JudgeSyncBaseCommandResult(resultLog)) { if (!JudgeSyncBaseCommandResult(resultLog)) {
imageSyncMessage.setCurrentProcedure(COMPRESS_IMAGE_TO_GZIP.getFuncName());
return; return;
} }
String gzipFileName = resultLog.get(0); String gzipFileName = resultLog.get(0);
@@ -123,6 +149,7 @@ public class ImageFuncScheduler {
imageSyncFuncArgs.set(2, gzipFileName); imageSyncFuncArgs.set(2, gzipFileName);
resultLog = funcService.callImageFuncService(innerWorkerAgentName, UPLOAD_GZIP_TO_OSS, imageSyncFuncArgs); resultLog = funcService.callImageFuncService(innerWorkerAgentName, UPLOAD_GZIP_TO_OSS, imageSyncFuncArgs);
if (!JudgeSyncBaseCommandResult(resultLog)) { if (!JudgeSyncBaseCommandResult(resultLog)) {
imageSyncMessage.setCurrentProcedure(UPLOAD_GZIP_TO_OSS.getFuncName());
return; return;
} }
@@ -135,20 +162,27 @@ public class ImageFuncScheduler {
// outside agent // outside agent
resultLog = funcService.callImageFuncService(outsideAgentTopicName, DOWNLOAD_GZIP_IMAGE_FILE, imageSyncFuncArgs); resultLog = funcService.callImageFuncService(outsideAgentTopicName, DOWNLOAD_GZIP_IMAGE_FILE, imageSyncFuncArgs);
if (!JudgeSyncBaseCommandResult(resultLog)) { if (!JudgeSyncBaseCommandResult(resultLog)) {
imageSyncMessage.setCurrentProcedure(DOWNLOAD_GZIP_IMAGE_FILE.getFuncName());
return; return;
} }
resultLog = funcService.callImageFuncService(outsideAgentTopicName, LOAD_DOCKER_IMAGE_FROM_GZIP, imageSyncFuncArgs); resultLog = funcService.callImageFuncService(outsideAgentTopicName, LOAD_DOCKER_IMAGE_FROM_GZIP, imageSyncFuncArgs);
if (!JudgeSyncBaseCommandResult(resultLog)) { if (!JudgeSyncBaseCommandResult(resultLog)) {
imageSyncMessage.setCurrentProcedure(LOAD_DOCKER_IMAGE_FROM_GZIP.getFuncName());
return; return;
} }
resultLog = funcService.callImageFuncService(outsideAgentTopicName, PUSH_IMAGE_TO_TARGET_HARBOR, imageSyncFuncArgs); resultLog = funcService.callImageFuncService(outsideAgentTopicName, PUSH_IMAGE_TO_TARGET_HARBOR, imageSyncFuncArgs);
if (!JudgeSyncBaseCommandResult(resultLog)) { if (!JudgeSyncBaseCommandResult(resultLog)) {
imageSyncMessage.setCurrentProcedure(PUSH_IMAGE_TO_TARGET_HARBOR.getFuncName());
return; return;
} }
resultLog = funcService.callImageFuncService(outsideAgentTopicName, UPDATE_IMAGE_TAG, imageSyncFuncArgs); resultLog = funcService.callImageFuncService(outsideAgentTopicName, UPDATE_IMAGE_TAG, imageSyncFuncArgs);
if (!JudgeSyncBaseCommandResult(resultLog)) { if (!JudgeSyncBaseCommandResult(resultLog)) {
imageSyncMessage.setCurrentProcedure(UPDATE_IMAGE_TAG.getFuncName());
return; return;
} }
imageSyncMessage.setCurrentProcedure(FINISHED.getFuncName());
imageSyncMessage.setIsSyncFinished(true);
} }
} }

View File

@@ -0,0 +1,80 @@
package io.wdd.pusher;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.wdd.pusher.beans.NtfyReceiveMessage;
import io.wdd.pusher.beans.PushMessageType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@Service
@Slf4j
public class MessagePusher {
@Resource
ObjectMapper objectMapper;
@Value("${octopus.notify.pusher_url}")
String pushServerUrl;
public NtfyReceiveMessage Send(Object sendMessage, PushMessageType pushMessageType) {
// Create a RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
// Define the URL to send the request to
if (pushServerUrl.endsWith("/")) {
pushServerUrl.substring(0, pushServerUrl.length() - 1);
}
String url = pushServerUrl + pushMessageType.getUri();
// Define the JSON payload
String jsonPayload = "";
try {
jsonPayload = objectMapper.writeValueAsString(sendMessage);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
// Create a HttpHeaders instance to add authentication information
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Authorization", "Bearer tk_zvdb67fwj1hrjivkq3ga9z7u63av5");
// Create a MultiValueMap to add additional headers
// MultiValueMap<String, String> additionalHeaders = new LinkedMultiValueMap<>();
// additionalHeaders.add("X-Custom-Header", "Custom-Value");
// headers.putAll(additionalHeaders);
// Send the POST request
ResponseEntity<String> response = restTemplate.postForEntity(url, jsonPayload, String.class, headers);
// Check the response status code
NtfyReceiveMessage ntfyReceiveMessage = null;
if (response.getStatusCode().is2xxSuccessful()) {
// Process the response body (JSON)
String responseBody = response.getBody();
try {
ntfyReceiveMessage = objectMapper.readValue(responseBody, NtfyReceiveMessage.class);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
// ...
} else {
// Handle the error response
// ...
log.error("Error sending message: {} with code: {}", response.getStatusCode(), jsonPayload);
}
return ntfyReceiveMessage;
}
}

View File

@@ -1,33 +0,0 @@
package io.wdd.pusher;
import io.wdd.pusher.core.model.ClientType;
import io.wdd.pusher.core.publish.PubClient;
import io.wdd.pusher.core.publish.PubClientImpl;
import io.wdd.pusher.core.publish.PubServiceImpl;
public final class NtfyClient {
private PubClient pubClient;
public NtfyClient(ClientType type) {
switch (type) {
case PUB:
PubServiceImpl pubService = new PubServiceImpl();
this.pubClient = new PubClientImpl(pubService);
break;
case SUB:
break;
default:
throw new IllegalArgumentException("Invalid client type");
}
}
public PubClient getClient() {
return pubClient;
}
}

View File

@@ -0,0 +1,27 @@
package io.wdd.pusher.beans;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class CmiiUpdateMessage {
@JsonProperty("Namespace")
private String namespace;
@JsonProperty("AppName")
private String appName;
@JsonProperty("FromTag")
private String fromTag;
@JsonProperty("ToTag")
private String toTag;
@JsonProperty("Replicas")
private String replicas;
@JsonProperty("DeployStatus")
private Boolean deployStatus;
}

View File

@@ -0,0 +1,30 @@
package io.wdd.pusher.beans;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class ImageSyncMessage {
private String imageFullName;
private String projectName;
private String projectNameSpace;
private String projectMasterIP;
private String projectMasterTopicName;
private String innerWorkTopicName;
private String currentProcedure;
private Boolean isSyncFinished;
}

View File

@@ -0,0 +1,43 @@
package io.wdd.pusher.beans;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class NtfyReceiveMessage {
@JsonProperty("ID")
private String id;
@JsonProperty("Event")
private String event;
@JsonProperty("Time")
private Integer time;
@JsonProperty("Topic")
private String topic;
@JsonProperty("Message")
private String message;
@JsonProperty("Title")
private String title;
@JsonProperty("Priority")
private Integer priority;
@JsonProperty("Tags")
private Object tags;
@JsonProperty("Click")
private String click;
@JsonProperty("Icon")
private String icon;
@JsonProperty("Attachment")
private Object attachment;
@JsonProperty("TopicURL")
private String topicURL;
@JsonProperty("SubscriptionID")
private String subscriptionID;
@JsonProperty("Raw")
private String raw;
}

View File

@@ -0,0 +1,55 @@
package io.wdd.pusher.beans;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class NtfySendMessage {
@JsonProperty("id")
private String id;
@JsonProperty("time")
private Integer time;
@JsonProperty("expires")
private Integer expires;
@JsonProperty("event")
private String event;
@JsonProperty("topic")
private String topic;
@JsonProperty("priority")
private Integer priority;
@JsonProperty("tags")
private List<String> tags;
@JsonProperty("click")
private String click;
@JsonProperty("attachment")
private AttachmentDTO attachment;
@JsonProperty("title")
private String title;
@JsonProperty("message")
private String message;
@NoArgsConstructor
@Data
public static class AttachmentDTO {
@JsonProperty("name")
private String name;
@JsonProperty("type")
private String type;
@JsonProperty("size")
private Integer size;
@JsonProperty("expires")
private Integer expires;
@JsonProperty("url")
private String url;
}
}

View File

@@ -0,0 +1,28 @@
package io.wdd.pusher.beans;
import lombok.Getter;
@Getter
public enum PushMessageType {
CMII_UPDATE(
"/cmii/update",
"更新CMII应用的消息通知类型"
),
IMAGE_SYNC(
"/image/sync",
"更新镜像同步的消类型"
);
String uri;
String description;
PushMessageType(String uri, String description) {
this.uri = uri;
this.description = description;
}
}

View File

@@ -1,14 +0,0 @@
package io.wdd.pusher.core.common;
public class NtfyConstants {
public static final String DEFAULT_URL = "https://ntfy.sh/";
public static final String POST = "POST";
public static final String CONTENT_TYPE = "Content-Type";
public static final String DEFAULT_HOST = "ntfy.sh";
public static final String NTFY_CONNECTION_ERROR_MSG = "Unable to connect to ntfy host";
public static final String CONNECTION_ERROR_MSG = "Unable to open connection";
public static final String HTTPS = "https://";
public static final String GET = "GET";
public static final String JSON = "json";
}

View File

@@ -1,20 +0,0 @@
package io.wdd.pusher.core.exception;
public class NtfyConnectionException extends Exception {
public NtfyConnectionException() {
super();
}
public NtfyConnectionException(String message) {
super(message);
}
public NtfyConnectionException(String message, Throwable cause) {
super(message, cause);
}
public NtfyConnectionException(Throwable cause) {
super(cause);
}
}

View File

@@ -1,24 +0,0 @@
package io.wdd.pusher.core.exception;
public class NtfyException extends Exception {
public NtfyException() {
super();
}
public NtfyException(String message) {
super(message);
}
public NtfyException(String message, Throwable cause) {
super(message, cause);
}
public NtfyException(Throwable cause) {
super(cause);
}
protected NtfyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@@ -1,24 +0,0 @@
package io.wdd.pusher.core.exception;
public class NtfyStreamingException extends Exception {
public NtfyStreamingException() {
super();
}
public NtfyStreamingException(String message) {
super(message);
}
public NtfyStreamingException(String message, Throwable cause) {
super(message, cause);
}
public NtfyStreamingException(Throwable cause) {
super(cause);
}
protected NtfyStreamingException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@@ -1,19 +0,0 @@
package io.wdd.pusher.core.model;
public enum ACTIONS {
VIEW("view"),
BROADCAST("broadcast"),
HTTP("http");
private final String name;
ACTIONS(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

View File

@@ -1,49 +0,0 @@
package io.wdd.pusher.core.model;
public class Action {
private ACTIONS action;
private String label;
private String url;
private boolean clear;
private String body;
public ACTIONS getAction() {
return action;
}
public void setAction(ACTIONS action) {
this.action = action;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public boolean isClear() {
return clear;
}
public void setClear(boolean clear) {
this.clear = clear;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}

View File

@@ -1,6 +0,0 @@
package io.wdd.pusher.core.model;
public enum ClientType {
PUB, SUB, STREAM;
}

View File

@@ -1,381 +0,0 @@
package io.wdd.pusher.core.model;
import java.util.Base64;
import java.util.List;
/**
* This class represents a message object for publishing/ sending notification message.
* It contains various properties related to the structure of the notification.
*/
public class NtfyRequest {
/**
* The topic to which you are publishing the message.
*/
private String topic;
/**
* The actual message content to be published. It can contain markdown as well.
*/
private String message;
/**
* The host or source to which you are publishing.
*/
private String host;
/**
* The title or subject of the message.
*/
private String title;
/**
* The priority level of the message.
*/
private PRIORITY priority;
/**
* A list of tags associated with the message.
*/
private List<String> tags;
/**
* The URL associated with the message.
*/
private String url;
/**
* Indicates whether the message content is in Markdown format.
*/
private boolean isMarkdown;
/**
* A list of actions related to the message.
*/
private List<Action> actions;
/**
* An attachment associated with the message. This will be the url linked of the attachment file.
*/
private String attach;
/**
* This local file that needs to be attached with the message,
*/
private String fileName;
/**
* The icon image url that needs to be used in the notification
*/
private String icon;
/**
* The email address to which the notification is to be sent.
*/
private String email;
/**
* The phone number to which the notification will be read to via call.
*/
private String phone;
/**
* Access token, generated in ntfy CLI
*/
private String accessToken;
/**
* Basic auth in format username:password
*/
private String authToken;
/**
* Get the auth token to authenticate to Server
*
* @return auth token as String
*/
public String getAuthToken() {
return this.authToken;
}
/**
* Sets the auth token (Base64 of username:password)
*
* @param userCombo username/password combo for generation of access token
*/
public void setAuthToken(String userCombo) {
this.authToken = Base64.getEncoder().encodeToString(userCombo.getBytes());
}
/**
* Get the accessToken for Authentication
*
* @return access token
*/
public String getAccessToken() {
return this.accessToken;
}
/**
* @param accessToken The authToken from CLI
*/
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
/**
* Get the phone number to which the notification will be read via a call.
*
* @return The phone number as a String.
*/
public String getPhone() {
return phone;
}
/**
* Set the phone number to which the notification will be read via a call.
*
* @param phone The phone number to set as a String.
*/
public void setPhone(String phone) {
this.phone = phone;
}
/**
* Get the email address to which the notification is to be sent.
*
* @return The email address as a String.
*/
public String getEmail() {
return email;
}
/**
* Set the email address to which the notification is to be sent.
*
* @param email The email address to set as a String.
*/
public void setEmail(String email) {
this.email = email;
}
/**
* Get the icon image URL that needs to be used in the notification.
*
* @return The icon image URL as a String.
*/
public String getIcon() {
return icon;
}
/**
* Set the icon image URL that needs to be used in the notification.
*
* @param icon The icon image URL to set as a String.
*/
public void setIcon(String icon) {
this.icon = icon;
}
/**
* Get the name of the local file that needs to be attached with the message.
*
* @return The file name as a String.
*/
public String getFileName() {
return fileName;
}
/**
* Set the name of the local file that needs to be attached with the message.
*
* @param fileName The file name to set as a String.
*/
public void setFileName(String fileName) {
this.fileName = fileName;
}
/**
* Get the attachment url associated with the message.
*
* @return The attachment url as a String.
*/
public String getAttach() {
return attach;
}
/**
* Set the attachment url for the message.
*
* @param attach The attachment url to set as a String.
*/
public void setAttach(String attach) {
this.attach = attach;
}
/**
* Get the list of actions related to the message.
*
* @return A list of Action objects.
*/
public List<Action> getActions() {
return actions;
}
/**
* Set the list of actions for the message.
*
* @param actions A list of Action objects to set.
*/
public void setActions(List<Action> actions) {
this.actions = actions;
}
/**
* Check if the message content is in Markdown format.
*
* @return True if the message content is in Markdown, false otherwise.
*/
public boolean isMarkdown() {
return isMarkdown;
}
/**
* Set whether the message content is in Markdown format.
*
* @param markdown True to set the message content as Markdown, false otherwise.
*/
public void setMarkdown(boolean markdown) {
isMarkdown = markdown;
}
/**
* Get the URL associated with the message.
*
* @return The URL as a String.
*/
public String getUrl() {
return url;
}
/**
* Set the URL for the message.
*
* @param url The URL to set as a String.
*/
public void setUrl(String url) {
this.url = url;
}
/**
* Get the actual message content.
*
* @return The message content as a String.
*/
public String getMessage() {
return message;
}
/**
* Set the message content.
*
* @param message The message content to set as a String.
*/
public void setMessage(String message) {
this.message = message;
}
/**
* Get the host or source of the message.
*
* @return The host as a String.
*/
public String getHost() {
return host;
}
/**
* Set the host or source of the message.
*
* @param host The host to set as a String.
*/
public void setHost(String host) {
this.host = host;
}
/**
* Get the title or subject of the message.
*
* @return The title as a String.
*/
public String getTitle() {
return title;
}
/**
* Set the title or subject of the message.
*
* @param title The title to set as a String.
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Get the priority level of the message.
*
* @return The priority level as a PRIORITY enum value.
*/
public PRIORITY getPriority() {
return priority;
}
/**
* Set the priority level of the message.
*
* @param priority The priority level to set as a PRIORITY enum value.
*/
public void setPriority(PRIORITY priority) {
this.priority = priority;
}
/**
* Get the list of tags associated with the message.
*
* @return A list of tags as Strings.
*/
public List<String> getTags() {
return tags;
}
/**
* Set the list of tags associated with the message.
*
* @param tags A list of tags to set as Strings.
*/
public void setTags(List<String> tags) {
this.tags = tags;
}
/**
* Get the topic to which the message is published.
*
* @return The topic as a String.
*/
public String getTopic() {
return topic;
}
/**
* Set the topic to which the message is published.
*
* @param topic The topic to set as a String.
*/
public void setTopic(String topic) {
this.topic = topic;
}
}

View File

@@ -1,27 +0,0 @@
package io.wdd.pusher.core.model;
public enum PRIORITY {
MAX("Max", 5),
HIGH("High", 4),
DEFAULT("Default", 3),
LOW("Low", 2),
MIN("Min", 1);
private final String name;
private final int level;
PRIORITY(String name, int level) {
this.name = name;
this.level = level;
}
public String getName() {
return name;
}
public int getLevel() {
return level;
}
}

View File

@@ -1,5 +0,0 @@
package io.wdd.pusher.core.model;
public class PublishResponse {
}

View File

@@ -1,117 +0,0 @@
package io.wdd.pusher.core.model;
import java.util.List;
public class RequestModel {
private String topic;
private String message;
private String title;
private List<String> tags;
private int priority;
private boolean markdown;
private List<Action> actions;
private String attach;
private String fileName;
private String icon;
private String email;
private String call;
public String getCall() {
return call;
}
public void setCall(String call) {
this.call = call;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getAttach() {
return attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public List<Action> getActions() {
return actions;
}
public void setActions(List<Action> actions) {
this.actions = actions;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public boolean isMarkdown() {
return markdown;
}
public void setMarkdown(boolean markdown) {
this.markdown = markdown;
}
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}

View File

@@ -1,25 +0,0 @@
package io.wdd.pusher.core.model;
public class StreamRequest {
private String host;
private String topic;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
}

View File

@@ -1,9 +0,0 @@
package io.wdd.pusher.core.publish;
import io.wdd.pusher.core.exception.NtfyException;
import io.wdd.pusher.core.model.NtfyRequest;
public interface PubClient {
String sendNotification(NtfyRequest ntfyRequest) throws NtfyException;
}

View File

@@ -1,26 +0,0 @@
package io.wdd.pusher.core.publish;
import io.wdd.pusher.core.exception.NtfyException;
import io.wdd.pusher.core.model.NtfyRequest;
import java.util.logging.Logger;
public class PubClientImpl implements PubClient {
private static final Logger logger = Logger.getLogger(PubClientImpl.class.getName());
private final PubService pubService;
public PubClientImpl(PubService pubService) {
this.pubService = pubService;
}
@Override
public String sendNotification(NtfyRequest ntfyRequest) throws NtfyException {
String response = pubService.publish(ntfyRequest);
if (null != response) {
logger.info("Response from server : " + response);
}
return response;
}
}

View File

@@ -1,9 +0,0 @@
package io.wdd.pusher.core.publish;
import io.wdd.pusher.core.exception.NtfyException;
import io.wdd.pusher.core.model.NtfyRequest;
public interface PubService {
String publish(NtfyRequest ntfyRequest) throws NtfyException;
}

View File

@@ -1,117 +0,0 @@
package io.wdd.pusher.core.publish;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.wdd.pusher.core.common.NtfyConstants;
import io.wdd.pusher.core.exception.NtfyConnectionException;
import io.wdd.pusher.core.exception.NtfyException;
import io.wdd.pusher.core.model.NtfyRequest;
import io.wdd.pusher.core.model.PRIORITY;
import io.wdd.pusher.core.model.RequestModel;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.logging.Logger;
public class PubServiceImpl implements PubService {
private static final Logger logger = Logger.getLogger(PubServiceImpl.class.getName());
@Override
public String publish(NtfyRequest request) throws NtfyException {
return publishMessage(request);
}
private String publishMessage(NtfyRequest request) throws NtfyException {
String response = null;
try {
if (null == request.getHost()) {
request.setUrl(NtfyConstants.DEFAULT_URL);
request.setHost(NtfyConstants.DEFAULT_HOST);
} else {
request.setUrl(NtfyConstants.HTTPS + request.getHost() + "/");
}
if (null == request.getPriority()) {
request.setPriority(PRIORITY.DEFAULT);
}
response = sendPublishRequest(request);
} catch (IOException e) {
logger.severe(NtfyConstants.CONNECTION_ERROR_MSG);
throw new NtfyException(e);
} catch (NtfyConnectionException e) {
logger.severe(NtfyConstants.NTFY_CONNECTION_ERROR_MSG);
throw new NtfyException(e);
} catch (Exception e) {
throw new RuntimeException(e);
}
return response;
}
private String sendPublishRequest(NtfyRequest request) throws Exception {
try {
URL obj = new URL(request.getUrl());
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod(NtfyConstants.POST);
con.setConnectTimeout(10000);
con.setRequestProperty(NtfyConstants.CONTENT_TYPE, "application/json");
//handle authentication (if supplied)
if (request.getAccessToken() != null) {
con.setRequestProperty("Authorization", "Bearer " + request.getAccessToken());
} else if (request.getAuthToken() != null) {
con.setRequestProperty("Authorization", "Basic " + request.getAuthToken());
}
// Enable input/output streams
con.setDoOutput(true);
try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) {
wr.writeBytes(new ObjectMapper().writeValueAsString(createPublishRequest(request)));
wr.flush();
}
// Get the response from the server
int responseCode = con.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
StringBuilder response = new StringBuilder();
try (java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(con.getInputStream()))) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
}
return response.toString();
} else {
throw new NtfyConnectionException(NtfyConstants.NTFY_CONNECTION_ERROR_MSG + " : " + responseCode + " " + con.getResponseMessage());
}
} catch (IOException e) {
throw new NtfyConnectionException(NtfyConstants.CONNECTION_ERROR_MSG, e);
}
}
private RequestModel createPublishRequest(NtfyRequest request) {
RequestModel model = new RequestModel();
model.setTopic(request.getTopic());
model.setMessage(request.getMessage());
model.setTitle(request.getTitle());
model.setTags(request.getTags());
model.setMarkdown(request.isMarkdown());
model.setPriority(request.getPriority().getLevel());
model.setActions(request.getActions());
model.setAttach(request.getAttach());
model.setFileName(request.getFileName());
model.setIcon(request.getIcon());
model.setEmail(request.getEmail());
model.setCall(request.getPhone());
return model;
}
}

View File

@@ -1,5 +0,0 @@
package io.wdd.pusher.core.stream;
public interface StreamingDataListener {
void onDataReceived(String data);
}

View File

@@ -1,63 +0,0 @@
package io.wdd.pusher.core.stream;
import io.wdd.pusher.core.common.NtfyConstants;
import io.wdd.pusher.core.exception.NtfyStreamingException;
import io.wdd.pusher.core.model.StreamRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class StreamingService {
private final String streamingUrl;
private boolean running;
private StreamingDataListener dataListener;
public StreamingService(StreamRequest request) {
this.streamingUrl = NtfyConstants.HTTPS + request.getHost() + "/" +
request.getTopic() + "/" + NtfyConstants.JSON;
}
public void start() throws NtfyStreamingException {
try {
running = true;
Thread streamThread = new Thread(() -> {
try {
URL url = new URL(streamingUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(NtfyConstants.GET);
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while (running) {
String line = reader.readLine();
if (line != null) {
if (dataListener != null) {
dataListener.onDataReceived(line);
}
}
}
reader.close();
connection.disconnect();
} catch (IOException e) {
System.err.println(e.getMessage());
}
});
streamThread.start();
} catch (Exception e) {
throw new NtfyStreamingException(NtfyConstants.CONNECTION_ERROR_MSG, e);
}
}
public void stop() {
running = false;
}
public void setDataListener(StreamingDataListener listener) {
this.dataListener = listener;
}
}

View File

@@ -1,40 +0,0 @@
package io.wdd.pusher.example;
import io.wdd.pusher.NtfyClient;
import io.wdd.pusher.core.exception.NtfyException;
import io.wdd.pusher.core.model.*;
import io.wdd.pusher.core.publish.PubClient;
import java.util.ArrayList;
import java.util.List;
public class PublishExample {
public static void main(String[] args) throws NtfyException {
PubClient client = new NtfyClient(ClientType.PUB).getClient();
NtfyRequest request = new NtfyRequest();
request.setTopic("test_ntfy2");
request.setMessage("Look ma, **bold text**, *italics*, ...");
request.setTitle("This is the obj msg");
request.setPriority(PRIORITY.MAX);
request.setAttach("https://media.licdn.com/dms/image/D4E03AQEZTNXuX3kG7g/profile-displayphoto-shrink_400_400/0/1669618932666?e=1699488000&v=beta&t=q2z_UDFvwTZa02SligKZqgwk66BjuXQZxWtQF_K1Jqw");
request.setFileName("Screenshot.png");
request.setIcon("https://styles.redditmedia.com/t5_32uhe/styles/communityIcon_xnt6chtnr2j21.png");
request.setEmail("mahesh.b.pec@gmail.com");
request.setPhone("");
Action action = new Action();
action.setAction(ACTIONS.VIEW);
action.setLabel("Open github");
action.setUrl("https://github.com/MaheshBabu11/ntfy-java");
action.setClear(true);
List<Action> actions = new ArrayList<>(List.of(action));
List<String> tags = new ArrayList<>(List.of("+1", "warning"));
request.setTags(tags);
request.setMarkdown(true);
request.setActions(actions);
client.sendNotification(request);
}
}

View File

@@ -1,27 +0,0 @@
package io.wdd.pusher.example;
import io.wdd.pusher.core.exception.NtfyStreamingException;
import io.wdd.pusher.core.model.StreamRequest;
import io.wdd.pusher.core.stream.StreamingService;
public class StreamingExample {
public static void main(String[] args) throws NtfyStreamingException {
StreamRequest request = new StreamRequest();
request.setHost("ntfy.sh");
request.setTopic("test_ntfy2");
StreamingService streamingConnection = new StreamingService(request);
streamingConnection.setDataListener(data -> {
// Process the incoming data here
System.out.println("Received data: " + data);
});
// Start the streaming connection
streamingConnection.start();
// Keep the connection open and receive data indefinitely
// To stop the connection, call streamingConnection.stop()
}
}

View File

@@ -96,8 +96,8 @@ octopus:
notify: notify:
# 消息通知的URL地址 # 消息通知的URL地址
pusher_url: http://192.168.35.71:8080 pusher_url: http://192.168.35.71:8080
# 发送消息的密钥 # 发送消息的密钥 不需要使用
access_token: 123456 access_token: tk_zvdb67fwj1hrjivkq3ga9z7u63av5
message: message:
# agent boot up default common exchange # agent boot up default common exchange
init_exchange: InitExchange init_exchange: InitExchange

View File

@@ -1,34 +0,0 @@
package io.wdd.pusher;
import io.wdd.pusher.core.exception.NtfyException;
import io.wdd.pusher.core.model.ClientType;
import io.wdd.pusher.core.model.NtfyRequest;
import io.wdd.pusher.core.model.PRIORITY;
import io.wdd.pusher.core.publish.PubClient;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class PusherTest {
@Test
public void test() {
PubClient client = new NtfyClient(ClientType.PUB).getClient();
NtfyRequest ntfyRequest = new NtfyRequest();
ntfyRequest.setHost("push.107421.xyz");
ntfyRequest.setTopic("octopus");
ntfyRequest.setTitle("来自Java的测试推送");
ntfyRequest.setPriority(PRIORITY.HIGH);
ntfyRequest.setAccessToken("tk_zvdb67fwj1hrjivkq3ga9z7u63av5");
ntfyRequest.setMessage("这是一条来自Java的测试推送");
ntfyRequest.setAuthToken("tk_zvdb67fwj1hrjivkq3ga9z7u63av5");
try {
client.sendNotification(ntfyRequest);
} catch (NtfyException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -44,7 +44,7 @@ public class TestImageSyncScheduler {
ArrayList<String> ImageFullNameList = new ArrayList<>(List.of( ArrayList<String> ImageFullNameList = new ArrayList<>(List.of(
// "harbor.cdcyy.com.cn/cmii/cmii-live-operator:5.2.0", // "harbor.cdcyy.com.cn/cmii/cmii-live-operator:5.2.0",
// "harbor.cdcyy.com.cn/cmii/cmii/srs:v5.0.195" // "harbor.cdcyy.com.cn/cmii/cmii/srs:v5.0.195"
"harbor.cdcyy.com.cn/cmii/cmii-uav-industrial-portfolio:5.4.0-cqly-042802" "harbor.cdcyy.com.cn/cmii/cmii-uav-mission:5.3.0-cqly-042901"
)); ));
Boolean downloadAndCompressOnly = false; Boolean downloadAndCompressOnly = false;

View File

@@ -0,0 +1,51 @@
package io.wdd.server.pusher;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.wdd.pusher.MessagePusher;
import io.wdd.pusher.beans.*;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest
public class PusherTest {
@Resource
MessagePusher messagePusher;
@Resource
ObjectMapper objectMapper;
@Test
public void test() {
NtfySendMessage ntfySendMessage = NtfySendMessage.builder()
.title("来自Java的测试内容")
.priority(1)
.message("Hello World")
.build();
CmiiUpdateMessage build = CmiiUpdateMessage.builder().appName("cmii-uav-gateway").namespace("uavcloud-dev").fromTag("1.0.0").toTag("5.0.0").replicas("1").deployStatus(Boolean.TRUE).build();
System.out.println("ntfySendMessage = " + ntfySendMessage);
NtfyReceiveMessage ntfyReceiveMessage = messagePusher.Send(build, PushMessageType.CMII_UPDATE);
System.out.println("ntfyReceiveMessage = " + ntfyReceiveMessage);
}
@SneakyThrows
@Test
public void testImageSyncMessage() {
ImageSyncMessage imageSyncMessage = new ImageSyncMessage();
String s = objectMapper.writeValueAsString(imageSyncMessage);
System.out.println("imageSyncMessage = " + s);
}
}