HashiCorp go-plugin包使用指南

1. 介绍 HashiCorp的go-plugin包是一个强大的Go语言插件系统,它通过RPC实现主程序和插件之间的通信。这个系统被广泛应用于HashiCorp的多个项目中,如Terraform、Nomad、Vault、Boundary和Waypoint等。本文将循序渐进地介绍go-plugin的使用方法,并提供简单易复现的例子。 2. 基本概念 go-plugin的工作原理是启动子进程并通过RPC进行通信。它支持标准的net/rpc和gRPC两种通信方式。主要特点包括: 插件是Go接口的实现 支持跨语言插件 支持复杂参数和返回值 支持双向通信 内置日志功能 协议版本控制 支持stdout/stderr同步 TTY保留 插件运行时主机升级 加密安全的插件 3. 单向通信示例 让我们从一个简单的单向通信示例开始,实现一个基本的问候插件。 3.1 定义接口 首先,我们需要定义插件将要实现的接口: // shared/interface.go package shared import "context" type Greeter interface { Greet(ctx context.Context, name string) (string, error) } 3.2 实现插件 接下来,我们实现这个接口作为一个插件: // plugin/main.go package main import ( "context" "fmt" "github.com/hashicorp/go-plugin" "path/to/your/shared" ) type GreeterPlugin struct{} func (g *GreeterPlugin) Greet(ctx context.Context, name string) (string, error) { return fmt.Sprintf("Hello, %s!", name), nil } var handshakeConfig = plugin....

如何为七牛已绑定域名的bucket获取Let's Encrypt证书

关于Let’s Encrypt证书 官网的说明是 一个为 2.25 亿个网站提供 TLS 证书的非盈利性证书颁发机构。 官网 : https://letsencrypt.org/zh-cn/ 获取证书的验证方式 目前有很多自动工具可以获取,需要有相关的域名或者服务器权限。认证的方式有三种,这里引用下官网的说明。验证方式 当您从 Let’s Encrypt 获得证书时,我们的服务器会验证您是否使用 ACME 标准定义的验证方式来验证您对证书中域名的控制权。 大多数情况下,验证由 ACME 客户端自动处理,但如果您需要做出一些更复杂的配置决策,那么了解更多有关它们的信息会很有用。 如果您不确定怎么做,请使用您的客户端的默认设置或使用 HTTP-01。 HTTP-01 验证 这是当今最常见的验证方式。 Let’s Encrypt 向您的 ACME 客户端提供一个令牌,然后您的 ACME 客户端将在您对 Web 服务器的 http://<你的域名>/.well-known/acme-challenge/(用提供的令牌替换 )路径上放置指定文件。 该文件包含令牌以及帐户密钥的指纹。 一旦您的 ACME 客户端告诉 Let’s Encrypt 文件已准备就绪,Let’s Encrypt 会尝试获取它(可能从多个地点进行多次尝试)。 如果我们的验证机制在您的 Web 服务器上找到了放置于正确地点的正确文件,则该验证被视为成功,您可以继续申请颁发证书。 如果验证检查失败,您将不得不再次使用新证书重新申请。 我们的 HTTP-01 验证最多接受 10 次重定向。 我们只接受目标为“http:”或“https:”且端口为 80 或 443 的重定向。 我们不目标为 IP 地址的重定向。 当被重定向到 HTTPS 链接时,我们不会验证证书是否有效(因为验证的目的是申请有效证书,所以它可能会遇到自签名或过期的证书)。 HTTP-01 验证只能使用 80 端口。 因为允许客户端指定任意端口会降低安全性,所以 ACME 标准已禁止此行为。...

Avalonia使用备忘

安装 模板 可以安装一些Avalonia的dotnet模板 dotnet new install Templates.Prism.Avalonia dotnet new install Avalonia.Templates IDE插件 Rider里面安装插件 AvaloniaRider VisualStudio安装插件 Avalonia for Visual Studio Avalonia 中的一些特性 Binding $parent 您可以使用$parent符号绑定到目标在逻辑上的父级: <Button DockPanel.Dock="Bottom" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" x:CompileBindings="False" Command="{Binding $parent[Window].DataContext.AddItem}">Add Item </Button> <Border Tag="Hello World!"> <TextBlock Text="{Binding $parent.Tag}"/> </Border> 也可以通过在$parent符号添加索引器绑定到父控件的父控件: <Border Tag="Hello World!"> <Border> <TextBlock Text="{Binding $parent[1].Tag}"/> </Border> </Border> 索引器从0开始,因此$parent[0]等同于$parent。 还可以按类型绑定到祖先: <Border Tag="Hello World!"> <Decorator> <TextBlock Text="{Binding $parent[Border].Tag}"/> </Decorator> </Border> 最后,您可以组合索引器和类型: <Border Tag="Hello World!"> <Border> <Decorator> <TextBlock Text="{Binding $parent[Border;1].Tag}"/> </Decorator> </Border> </Border> 如果需要在祖先类型中包含XAML命名空间,一般使用:字符:...

Buf使用备忘

Buf 工具针对于Schema驱动、基于 Protobuf 的 API 开发,为服务发布者和服务客户端提供可靠和更好的用户体验。简化了您的 Protobuf 管理策略,以便您可以专注于重要的事情。 下载安装 可以直接去buf的GitHub的release页面下载,其他的安装方式参考官方文档 使用 三个yaml文件 初次接触buf项目的时候,有个疑问就是buf项目中buf.yaml buf.gen.yaml buf.work.yaml这个三个文件的区别和用途。下面是简单的一个表,列出了三个文件的区别: 文件名 文件位置 说明 buf.yaml 每个proto模块定义的根目录 buf.yaml 配置的位置告诉 buf 在哪里搜索 .proto 文件,模块的依赖项以及如何处理导入 buf.gen.yaml 一般放在仓库的根目录 文件控制 buf generate 命令如何针对任何输入执行 protoc 插件 buf.work.yaml 一般放在仓库的根目录 定义项目需要哪些proto模块 示例目录结构: . ├── buf.gen.yaml ├── buf.work.yaml ├── proto │ ├── acme │ │ └── weather │ │ └── v1 │ │ └── weather.proto │ └── buf.yaml └── vendor └── protoc-gen-validate ├── buf.yaml └── validate └── validate....

浅析Jetbrains的产品版本和更新API设计

接口分析 单个产品信息接口 首先我们通过http抓包来看DataGrip这个产品查询接口,访问的接口地址为下面这个地址 https://data.services.jetbrains.com/products?code=DG&release.type=eap,rc,release&fields=distributions,link,name,releases&_=1690557030459 从接口上我们能看到有下面几个方面: graphql风格接口设计。 支持产品代码、软件包通道、软件平台的筛选。主要有下面几个: 平台 说明 Windows linux windowsZip windows压缩包 windowsARM64 mac macM1 该接口返回信息如下: { "DG": [ { "date": "2023-07-20", "type": "release", "downloads": { "linuxARM64": { "link": "https://download.jetbrains.com/datagrip/datagrip-2023.2-aarch64.tar.gz", "size": 570768510, "checksumLink": "https://download.jetbrains.com/datagrip/datagrip-2023.2-aarch64.tar.gz.sha256" }, "linux": { "link": "https://download.jetbrains.com/datagrip/datagrip-2023.2.tar.gz", "size": 569402212, "checksumLink": "https://download.jetbrains.com/datagrip/datagrip-2023.2.tar.gz.sha256" }, "thirdPartyLibrariesJson": { "link": "https://resources.jetbrains.com/storage/third-party-libraries/datagrip/datagrip-2023.2-third-party-libraries.json", "size": 62706, "checksumLink": "https://resources.jetbrains.com/storage/third-party-libraries/datagrip/datagrip-2023.2-third-party-libraries.json.sha256" }, "windows": { "link": "https://download.jetbrains.com/datagrip/datagrip-2023.2.exe", "size": 447884488, "checksumLink": "https://download.jetbrains.com/datagrip/datagrip-2023.2.exe.sha256" }, "windowsZip": { "link": "https://download.jetbrains.com/datagrip/datagrip-2023.2.win.zip", "size": 566939835, "checksumLink": "https://download....

Golang高效解码xml文件

xml处理需要引用encoding/xml包.一般推荐使用 xml.Decoder 替代 xml.Unmarshal。 xml.Decoder 是一个流式 XML 解码器,它可以边读取边解码,而不需要将整个 XML 文档加载到内存中。相比之下,xm1.Unmarshal 会将整个 XML 文档加载到内存中然后再进行解码。因此,对于大型 XML 文件,使用xml.Decoder 可以节省内存并提高性能。 小的Xml文件 下面是一个例子 package main import ( "encoding/xml" "os" "testing" ) type UserData struct { Name string `xml:"name"` Age int32 `xml:"age"` } type Pocket struct { Data []UserData `xml:"users"` } func TestXmlDecode(t *testing.T) { file, err := os.Open("testdata/userdata.xml") if err != nil { t.Fatal(err) } var pocket Pocket if err := xml.NewDecoder(file).Decode(&pocket); err != nil { t....

使用C#以编程方式切换Windows专注模式

缘起 最近需要以编程方式调用windows api实现windows10专注模式的切换,但是Google一圈,没有现成代码。找到的相关帖子要么是cpp的要么是rust的,而且是undocument的Windows api。 Csharp调用 以下是完整代码 public static class FocusAssistToogle { private const string NtdllDlDll = "ntdll.dll"; private const uint DataBufferSize = 4; private static readonly byte[] DisableDataBuf = { 0x00, 0x00, 0x00, 0x00 }; // 01仅优先通知 02 仅限闹钟 private static readonly byte[] EnableDataBuf = { 0x02, 0x00, 0x00, 0x00 }; [DllImport(NtdllDlDll, SetLastError = true)] private static extern int ZwUpdateWnfStateData( ref WnfSWnfStateName sWnfStateName, byte[] buffer, uint bufferSize, IntPtr previousStateData, IntPtr currentStateData, uint previousStateDataSize, uint currentStateDataSize); [StructLayout(LayoutKind....

Zig相关资源

博客 https://www.openmymind.net https://matklad.github.io https://kristoff.it 教程 https://zigbyexample.github.io Zig Cookbook https://ikrima.dev/dev-notes/zig/zig-crash-course/ https://ikrima.dev/dev-notes/zig/zig-metaprogramming/ https://zig.guide https://course.ziglang.cc Introduction to Zig Zig Common Tasks zig资讯 zig news 软件包 https://zig.pm

Zig语言快速参考

本文使用AI自动翻译,原文链接 第 0 章 - 入门 欢迎 Zig 是一种通用编程语言和工具链,用于维护健壮、最佳和可重用的软件。 警告:最新的主要版本是 0.10.1 - Zig 仍然是 1.0 之前的版本;仍然不建议在生产中使用,并且您可能会遇到编译器错误。 要遵循本指南,我们假设您已经: 先前的编程经验 对低级编程概念的一些理解 了解 C、C++、Rust、Go、Pascal 或类似语言将有助于遵循本指南。您应该有一个可用的编辑器、终端和互联网连接。本指南是非官方的,与 Zig Software Foundation 无关,旨在从一开始就按顺序阅读。 Installation 本指南假设您使用 Zig 的主版本而不是最新的主要版本,这意味着从网站下载二进制文件或从源代码编译;您的包管理器中的 Zig 版本可能已过时。本指南不支持 Zig 0.10.1。 从以下位置下载并提取 Zig 的预构建主二进制文件: https://ziglang.org/download/ 将 Zig 添加到您的路径 linux, macos, bsd 将 Zig 二进制文件的位置添加到 PATH 环境变量中。对于安装,请添加 export PATH=$PATH:~/zig 或类似于 /etc/profile(系统范围)或 $HOME/.profile。如果这些更改没有立即应用,请从 shell 运行该行。 windows a) 系统范围(admin powershell) [Environment]::SetEnvironmentVariable( "Path", [Environment]::GetEnvironmentVariable("Path", "Machine") + ";C:\your-path\zig-windows-x86_64-your-version", "Machine" ) b) 用户级别(powershell)...

Golang 防火墙编程

非编程方式 Windows 使用netsh方式进行防火墙规则的维护 Linux 编程方式 Windows Tailscale开发了一个应用WFP的库inet.af/wf 。参考参考链接。在tailscale中的封装代码如下(源链接): // Copyright (c) Tailscale Inc & AUTHORS // SPDX-License-Identifier: BSD-3-Clause //go:build windows package wf import ( "fmt" "net/netip" "os" "golang.org/x/sys/windows" "inet.af/wf" "tailscale.com/net/netaddr" ) // Known addresses. var ( linkLocalRange = netip.MustParsePrefix("ff80::/10") linkLocalDHCPMulticast = netip.MustParseAddr("ff02::1:2") siteLocalDHCPMulticast = netip.MustParseAddr("ff05::1:3") linkLocalRouterMulticast = netip.MustParseAddr("ff02::2") ) type direction int const ( directionInbound direction = iota directionOutbound directionBoth ) type protocol int const ( protocolV4 protocol = iota protocolV6 protocolAll ) // getLayers returns the wf....