Git Product home page Git Product logo

plugins's Introduction

Plugins License GoDoc Unit Tests Vistors

Go plugins is a place for community maintained plugins.

Overview

Micro tooling is built on a powerful pluggable architecture. Plugins can be swapped out with zero code changes. This repository contains plugins for all micro related tools. Read on for further info.

Getting Started

Contents

Contents of this repository:

Directory Description
Broker PubSub messaging; NATS, NSQ, RabbitMQ, Kafka
Client RPC Clients; gRPC, HTTP
Codec Message Encoding; BSON, Mercury
Micro Micro Toolkit Plugins
Registry Service Discovery; Etcd, Gossip, NATS
Selector Load balancing; Label, Cache, Static
Server RPC Servers; gRPC, HTTP
Transport Bidirectional Streaming; NATS, RabbitMQ
Wrapper Middleware; Circuit Breakers, Rate Limiting, Tracing, Monitoring

Usage

Plugins can be added to go-micro in the following ways. By doing so they'll be available to set via command line args or environment variables.

Import the plugins in a plugins.go file

package main

import (
	_ "github.com/go-micro/plugins/v5/broker/rabbitmq"
	_ "github.com/go-micro/plugins/v5/registry/kubernetes"
	_ "github.com/go-micro/plugins/v5/transport/nats"
)

Create your service and ensure you call service.Init

package main

import (
	"go-micro.dev/v5"
)

func main() {
	service := micro.NewService(
		// Set service name
		micro.Name("my.service"),
	)

	// Parse CLI flags
	service.Init()
}

Build your service

go build -o service ./main.go ./plugins.go

Env

Use environment variables to set the

MICRO_BROKER=rabbitmq \
MICRO_REGISTRY=kubernetes \ 
MICRO_TRANSPORT=nats \ 
./service

Flags

Or use command line flags to enable them

./service --broker=rabbitmq --registry=kubernetes --transport=nats

Options

Import and set as options when creating a new service

import (
	"go-micro.dev/v5"
	"github.com/go-micro/plugins/v5/registry/kubernetes"
)

func main() {
	registry := kubernetes.NewRegistry() //a default to using env vars for master API

	service := micro.NewService(
		// Set service name
		micro.Name("my.service"),
		// Set service registry
		micro.Registry(registry),
	)
}

Build

An anti-pattern is modifying the main.go file to include plugins. Best practice recommendation is to include plugins in a separate file and rebuild with it included. This allows for automation of building plugins and clean separation of concerns.

Create file plugins.go

package main

import (
	_ "github.com/go-micro/plugins/v5/broker/rabbitmq"
	_ "github.com/go-micro/plugins/v5/registry/kubernetes"
	_ "github.com/go-micro/plugins/v5/transport/nats"
)

Build with plugins.go

go build -o service main.go plugins.go

Run with plugins

MICRO_BROKER=rabbitmq \
MICRO_REGISTRY=kubernetes \
MICRO_TRANSPORT=nats \
service

plugins's People

Contributors

xpunch avatar davincible avatar asim avatar jochumdev avatar dbereza-machinify avatar kobergj avatar butonic avatar quexer avatar r3eg avatar keepstep avatar scs-11 avatar medivh-jay avatar qianwj avatar aduffeck avatar opvexe avatar mamadeusia avatar xiaomiusa87 avatar wkloucek avatar scukerman avatar rhafer avatar petrchalov avatar asynxc avatar dragonchaser avatar super-zhw avatar kuri-su avatar esivres avatar alexlast avatar

Stargazers

Akash Jadhav avatar Jeff Xie avatar Vinh Truong avatar  avatar  avatar  avatar Yehezkiel Dio Sinolungan avatar purya ghahremani avatar 长弓词 avatar  avatar  avatar centosR avatar Anh Geeky avatar 三万里高空 avatar zjw57 avatar Mohammed Saaduddin Ansari avatar chenfyun avatar Andy avatar Karlos Daniel Pires da Silva avatar Thanh Pham avatar  avatar Justice Nanhou avatar Singgih Dwindaru avatar jgbooks avatar Mark Lemieszewski avatar Cesc avatar zhanjunjie avatar  avatar Cioclea Doru Octavian avatar Mohammed Osama avatar Mohammad Kolagar avatar 김성조 avatar Mohammad Amin Ahmadi avatar Jozsef Oszlanczi avatar  avatar Dylan avatar Tina Aliakbarpour avatar JeffreyBool avatar Evan avatar suntong02 avatar Edson Michaque avatar  avatar Dhairy Tripathi avatar  avatar  avatar joestarzxh avatar  avatar Hoverhuang avatar Eko Muhammad Isa avatar  avatar fanguochao avatar zhang-jianqiang avatar dudu avatar  avatar  avatar Haofei Sun avatar lidaqi avatar Victoryship avatar  avatar  avatar  avatar Bobo avatar  avatar  avatar  avatar B avatar  avatar lidashuang avatar Ahmed avatar  avatar  avatar 雪痕 avatar Cody avatar  avatar peer avatar Bart van Kleef avatar luqmannul hakim avatar  avatar  avatar Nicola Benson avatar Morya avatar Tresor Kambembo  avatar Mourad Maatoug avatar  avatar  avatar Rex Wu avatar Márk Bartos avatar Abraham Setya Nugraha avatar bosima avatar Henry.H avatar

Watchers

Lucian avatar  avatar Márk Bartos avatar  avatar  avatar 김성조 avatar  avatar  avatar  avatar

plugins's Issues

registry watch don't work ?why ?

func TestConsulRegistryWatcher(t *testing.T) {
	reg := consul.NewRegistry()

	go func() {
		time.Sleep(10 * time.Second)
		fmt.Println("====1000")
		err := reg.Register(&registry2.Service{
			Name:    "test.service",
			Version: "latest",
			Nodes: []*registry2.Node{
				{
					Id:      "test.node10",
					Address: "localhost:8080",
				},
			},
		})
		if err != nil {
			t.Fatalf("无法注册服务: %v", err)
		}
	}()

	go func() {
		time.Sleep(5 * time.Second)
		fmt.Println("====55")
		err := reg.Register(&registry2.Service{
			Name:    "test.service",
			Version: "latest",
			Nodes: []*registry2.Node{
				{
					Id:      "test.node12",
					Address: "localhost:8080",
				},
			},
		})
		if err != nil {
			t.Fatalf("无法更新服务: %v", err)
		}
	}()

	watcher, err := reg.Watch(registry2.WatchService("test.service"))
	if err != nil {
		t.Fatalf("无法创建Watcher: %v", err)
	}
	defer watcher.Stop()

	list, err := reg.GetService("test.service")
	assert.NoError(t, err)
	t.Log(list)

	for {
		fmt.Println("-----")
		event, err := watcher.Next()
		fmt.Println("++++++++")
		if err != nil {
			t.Fatalf("Watcher错误: %v", err)
		}
		t.Logf("收到Watcher事件: %v", event)
	}
}

plugins/blob/main/v4/config/source/consul/watcher.go watcher err

As I usage, ACL is enabled, where the token parameter type is missing, the watcher fails, or Plan constructed parameters should be provided where possible

wp, err := watch.Parse(map[string]interface{}{"type": "keyprefix", "prefix": key})

like this:

wp, err := watch.Parse(map[string]interface{}{"type": "keyprefix", "prefix": key,"token":token})

[BUG] invalid character '-' in numeric literal.

Describe the bug

I've recently switched the to go-micro v4 & started getting this error while using the function config.Load().

It was supposed to load the config instead I am getting this error -> invalid character '-' in numeric literal

How to reproduce the bug

func loadConfigFile() error {
	enc := yaml.NewEncoder()

	// Configmap Path
	configMapPath, set := common.GetEnvVar("CONFIGMAP_PATH", "./testdata", true)
	if !set {
		return common.GetErrEnvVar("CONFIGMAP_PATH")
	}
	// Configmap yaml file name
	configMapFile, set := common.GetEnvVar("CONFIGMAP_FILE", "data.yml", true)
	if !set {
		return common.GetErrEnvVar("CONFIGMAP_FILE")
	}
	// Secret Path
	secretPath, set := common.GetEnvVar("SECRET_PATH", "./testdata", true)
	if !set {
		return common.GetErrEnvVar("SECRET_PATH")
	}
	// Secret yaml file name
	secretFile, set := common.GetEnvVar("SECRET_FILE", "secrets.yml", true)
	if !set {
		return common.GetErrEnvVar("SECRET_FILE")
	}

	// Load config sources
	if err := config.Load(
		file.NewSource(
			file.WithPath(configMapPath+"/"+configMapFile),
			source.WithEncoder(enc)),
		file.NewSource(
			file.WithPath(secretPath+"/"+secretFile),
			source.WithEncoder(enc),
		)); err != nil {
		        fmt.Println(err)
		)
		return errLoadConfigFile
	}

	// Watch a value for changes
	watcher, err := config.Watch()
	if err != nil {
	       fmt.Println("Error 2!")
		)
		return errWatchFileError
	}

	go processConfig(watcher)
	return nil
}

Here's my sample struct file.

package structs

// Config structure that holds Configurations for Bot Components
type Config struct {
	Channels  []Channel `json:"channels"`
	Constants Constants `json:"constants"`
	Bot       Bot       `json:"tbot"`
	Views     []View    `json:"views"`
	// Secrets
	Readme  string `json:"README"`
	Project string `json:"project_id"`
}

type Channel struct {
	ID          string      `json:"id"`
	Bot         Bot         `json:"bot"`
	PagerDuty   PagerDuty   `json:"pagerduty"`
	XMatters    XMatters    `json:"xmatters"`
	Enps        Enps        `json:"enps"`
	IssueType   IssueType   `json:"issuetype"`
	Support     Support     `json:"support"`
	Suggestions Suggestions `json:"suggestions"`
	Core        string      `json:"core"`
	Views       []View      `json:"views"`
}

type Support struct {
	MessageOnly         bool          `json:"messageOnly"`
	IgnoreCode          string        `json:"ignorecode"`
	AckCode             string        `json:"ackcode"`
	ResolveCode         string        `json:"resolvecode"`
	ChannelsToJoin      []string      `json:"channelstojoin"`
	ResolveReactionName string        `json:"resolvereactionname"`
	MaximumMessages     int           `json:"maximummessages"`
	MessagesPerWarning  int           `json:"messagesperwarning"`
	CronConfig          []CronSetting `json:"cronconfig"`
	ThreadEmoji         string        `json:"threadEmoji"`
	NoOfMsgForHistory   int           `json:"noOfMsgForHistory"`
	RespondToHere       bool          `json:"respondToHere"`
	RespondToChannel    bool          `json:"respondToChannel"`
	SlashCommand        SlashCommand  `json:"slashCommand"`
}

type Suggestions struct {
	SlackSuggest           bool     `json:"slackSuggest"`        // Turns on Slack Suggestions for threads
	SearchChannelName      []string `json:"searchChannelName"`   // The channel names you want to search
	SearchChannelID        []string `json:"searchChannelID"`     // The channel ID's you want to search
	SearchMessageCount     []int    `json:"searchMessageCount"`  // The count for threads you want per channel
	Keywords               []string `json:"keywords"`            // The keywords you want to use for a custom message
	KeywordTemplateID      []string `json:"keywordTemplateID"`   // The template for the keywords for a custom message
	KeysForThreadSearch    []string `json:"keysForThreadSearch"` // The keywords for thread search
	ThreadSearchCharacters int      `json:"threadSearchCharacters"`
}

type SlashCommand struct {
	OnCall      string `json:"onCall"`
	MyOnCall    string `json:"myOnCall"`
	OpenTickets string `json:"openTickets"`
	TbotHelp    string `json:"tbotHelp"`
}

type PagerDuty struct {
	PagerDutyServiceID               string `json:"pagerdutyserviceid"`
	PagerDutyDefaultServiceID        string `json:"pagerdutydefaultserviceid"`
	PagerDutyIncidentUrgency         string `json:"pagerdutyincidenturgency"`
	PagerDutyIncidentDefaultUrgency  string `json:"pagerdutyincidentdefaulturgency"`
	PagerDutyIncidentPriority        string `json:"pagerdutyincidentpriority"`
	PagerDutyIncidentDefaultPriority string `json:"pagerdutyincidentdefaultpriority"`
	PagerDutyScheduleID              string `json:"pagerdutyscheduleid"`
	PagerDutyTeamID                  string `json:"pagerdutyteamid"`
}

type XMatters struct {
	HostName    string `json:"hostName"`
	GroupName   string `json:"groupID"`
	ServiceName string `json:"serviceName"`
	Severity    string `json:"severity"`
}

type Enps struct {
	Enable    bool   `json:"enable"`
	TableName string `json:"tableName"`
}

type IssueType struct {
	Enable    bool   `json:"enable"`
	TableName string `json:"tableName"`
}

// Bot structure that holds Configuration Bot Configuration
type Bot struct {
	Name           string `json:"name"`
	AppMention     string `json:"appmention"`
	ChannelName    string `json:"channelName"`
	IconURL        string `json:"iconurl"`
	EnableWebhooks bool   `json:"enablewebhooks"`
}

// Constants structure that holds constants
type Constants struct {
	Ack          string `json:"ack"`
	Resolve      string `json:"resolve"`
	Note         string `json:"note"`
	CreateTicket string `json:"create_ticket,omitempty"`
}

// View structure that holds view
type View struct {
	ID       string `json:"id"`
	Template string `json:"template"`
}

Here's the sample yaml file.

---
data:
    channels:
        - ID: "CHANNEL_ID"
          bot:
              appmention: "@bot"
              channelName: "#testing-channel"
              name: "bot"
              EnableWebhooks: false
          xmatters:
              HostName: "xmatters.com"
              GroupName: "xMatters-service" Test Team"
              ServiceName: "xMatters-service"
              Severity: ""
          support:
              IgnoreCode: ":tmobile:"
              NoOfMessageHistory: 0
              ThreadEmoji: "thread-please"
              slashCommand:
                  Help: "/slack-slash"
          suggestions:
              SlackSuggest: false
              ThreadSearchCharacters: 40
              SearchChannelName:
                  - "#slack-channel-name"
              SearchChannelID:
                  - "SOME_CHANNEL"
              SearchMessageCount:
                  - 1
          enps:
              enable: false
              tableName: "enps"
          issueType:
              enable: true
              tableName: "issueTeams"
          core: "support"
          views:
              - id: "welcome.json"
                template: |
                    {
                            "blocks": [
                                {
                                    "type": "section",
                                    "text": {
                                        "type": "mrkdwn",
                                        "text": "Hi <@{{ .User }}> :wave: Welcome to the Support Channel."
                                    }
                                },
                                {
                                    "type": "section",
                                    "text": {
                                        "type": "mrkdwn",
                                        "text": "Please select from the dropdown box and click submit! Then, please read the documentation before creating a ticket. Thank you!"
                                    }
                                }
                            ]
                    }

Environment

Go Version: please paste go version output here

GOVERSION="go1.19.5"

[FEATURE] Add support for grpc reflection

Is your feature request related to a problem? Please describe.

Add ability for grpc reflection to support web ui/grpc curl

Describe the solution you'd like
Should have some flag to pass to service.New to register reflection service on gRPC server Reference: https://github.com/grpc/grpc/blob/master/doc/server-reflection.md

Additional context
This is a duplicate for previous feature request: micro/go-micro#1181, But other one seems to have been closed without any merge into master

grpc shutdown advice

1680787350076

It is more appropriate to customize the timeout period here? Like net/HTTP, not all responses can be completed within 1 second

[BUG] github.com/asim/go-bson not found

go: downloading github.com/asim/go-bson v0.0.0-20160318195205-84522947cabd
bsonrpc.go:9:2: github.com/asim/[email protected]: invalid version: git fetch -f origin refs/heads/*:refs/heads/* refs/tags/*:refs/tags/* in /home/runner/go/pkg/mod/cache/vcs/21e914b1748907782789d893db54028cff7d9114adadce64be54e5c2b588956f: exit status 128:
	fatal: could not read Username for 'https://github.com/': terminal prompts disabled
Error: Process completed with exit code 1.

[FEATURE] v4/sync/etcd - add username/password options

Is your feature request related to a problem? Please describe.
Currently, the v4/sync/etcd plugin does not allow passing in a username/password for RBAC authentication with etcd, either embedded in the endpoint URL or as separate custom options.

Describe the solution you'd like
The etcd client library expects the username/password for RBAC authentication passed in the config, which is being defined here:
https://github.com/go-micro/plugins/blob/0ed40ba1aacebe0d38d871a6272f78125bf68dbc/v4/sync/etcd/etcd.go#L174-L177

Currently, the username / password are not being defined here, and embedding the username/password into the endpoint URL does not cause the etcd client to parse them out and use them for RBAC auth.

As such, the username/password could be parsed out of the sync.Nodes sync option, which isn't super ideal, or new etcd-specific credential options could be created and stored/retrieved from the option context.

Additional context
N/A

RabbitMQ reconnect causes multiple connections to be created

The reconnecting triggered after the RabbitMQ channel is closed will cause the client side and server level to maintain multiple connections simultaneously.

When chanNotifyClose receives an error, the RabbitMQ connection isn't closed. It immediately establishes a new connection and subsequently recreates a channel based on this new connection.
https://github.com/go-micro/plugins/blob/bc05fb076ce7165ca58cd960008407f42d8bbb23/v4/broker/rabbitmq/connection.go#L161

This can result in the client and server simultaneously holding both old and new connection resources. In this scenario, we can either manually close the old connection before reconnecting or reuse the existing connection resources.

how can i set the nacos GroupName

i use the [email protected] in my project , with nacos registry plugins, the question is how can i set the nacos client GroupName
my main.go code like this , i not found how can set that option.

clientConfig := *constant.NewClientConfig(
		constant.WithNotLoadCacheAtStart(true),
		constant.WithNamespaceId(global.RegistrySetting.NamespaceId),
		constant.WithCacheDir(global.RegistrySetting.CacheDir),
		constant.WithLogDir(global.RegistrySetting.LogDir),
	)
	registry := nacos.NewRegistry(nacos.WithClientConfig(clientConfig), nacos.WithAddress([]string{global.RegistrySetting.Host + ":" + strconv.Itoa(global.RegistrySetting.Port)}))


svc := micro.NewService(
		micro.Name(serviceName),
		micro.Registry(registry),
		micro.Config(serviceConfig),
	)

[FEATURE] v4/broker/rabbitmq - parallel message handling

Is your feature request related to a problem? Please describe.
Enhance v4/broker/rabbitmq plugin to allow for handling incoming broker messages in parallel.

Describe the solution you'd like
Currently, it seems the v4/broker/rabbitmq plugin processes messages serially, based on the code below:
https://github.com/go-micro/plugins/blob/0ed40ba1aacebe0d38d871a6272f78125bf68dbc/v4/broker/rabbitmq/rabbitmq.go#L142-L146

This is not ideal for throughput, particularly for messages that take time to process or their handlers end up blocking.

Additional context
This could be tied to the rabbitmq.PrefetchCount broker option, since that's a limitation of the max number of messages that are retrieved but not acknowledged at a time, but for backwards compatibility another option should probably be provided to enable parallelism.

[BUG]Issue with the nacos registry in web.NewService()

That reports an error when I use nacos registry in web.NewService():
panic: assignment to entry in nil map
My code:

package main

import (
	"user/config/config"
	"go-micro.dev/v4/web"
)

var (
	service = "go-layout"
	version = "latest"
)

func main() {
	srv := web.NewService(
		web.Name(service),
		web.Version(version),
		web.Registry(config.NewRegistry()),
		// web.Metadata(map[string]string{"version": version}),
	)
	srv.Run()
}
package config

import (
	"github.com/asim/go-micro/plugins/registry/nacos/v4"
	"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
	"go-micro.dev/v4/registry"
)

func NewRegistry() registry.Registry {
	DefaultClientConfig := constant.ClientConfig{
		NamespaceId: "45d1be27-88ab-487d-b0ba-c09557fcaf29",
	}
	r := nacos.NewRegistry(
		nacos.WithClientConfig(DefaultClientConfig),
		nacos.WithAddress([]string{
			"127.0.0.1:8848",
		}))
	return r
}

go.mod

module user

go 1.18

require (
	github.com/asim/go-micro/plugins/registry/nacos/v4 v4.0.0-20220404185419-6dedee5d8c2c
	github.com/nacos-group/nacos-sdk-go/v2 v2.0.1
	go-micro.dev/v4 v4.2.1
)

Debug code,I find it will be ok to add web.Metadat option in web.NewService().

Environment:
Go Version: go version go1.18 windows/amd64

plugins/v4/wrapper/breaker/hystrix/ readMe

hystrix.NewClientWrapper(hystrix.WithFilter(func(c context.Context, e error) error {
if e == ErrLetItPass {
return nil
}
return e
})

should be:
hystrix.NewClientWrapper(hystrix.WithFilter(func(c context.Context, e error) bool{
if e == ErrLetItPass {
return true
}
return false
})

[BUG] etcd plugin errors out on new project

Describe the bug

  1. What are you trying to do?
    I'm trying to use go-micro with the etcd registry
  2. What did you expect to happen?
    I expected the etcd plugin to be bundled with go-micro. I also expected it to work after pulling it in from the plugins explicitly.
  3. What happens instead?
    The error below

How to reproduce the bug:

If possible, please include a minimal code snippet here.

$ micro new service my_service
$ make proto update tidy
$ cd my_service
$ go run *.go --registry etcd
Registry etcd not found
exit status 1
$ go get github.com/asim/go-micro/plugins/registry/etcd/v4
<add to plugins.go>
$ go run *.go --registry etcd
# go.etcd.io/etcd/client/v3
../../go/pkg/mod/go.etcd.io/etcd/client/[email protected]/client.go:251:28: undefined: grpc.WithResolvers
../../go/pkg/mod/go.etcd.io/etcd/client/[email protected]/client.go:276:29: undefined: grpc.WithResolvers

Environment:
Go Version: please paste go version output here

go version go1.18.1 darwin/arm64

Add an option for consul http check

Currently there are only options to enable TCP/TTL service level checks in consul plugin. Need to extend it to support HTTP health checks as well

micro service reg consul by extranet ip

I have two micro services deployed on different pc, the two services reg the same consul by extranet ip. However, the second service can't access to first service by rpc.

consul start-up: consul agent -server -ui -bootstrap-expect=1 -data-dir=/data/consul -node=hostname -bind=0.0.0.0 -advertise=49.234.57.x -client=0.0.0.0

first service(go-micro-v3):

func main() {
    service := micro.NewService(
        micro.Name("first"),
        micro.Registry(consul.NewRegistry(registry.Addrs("49.234.57.x:8500"))),
    )
    service.Init()
    pb.RegisterFirstHandler(service.Server(), new(handler.First))
    service.Run()
}

second service(go-micro-v3):

func main() {
    service := micro.NewService(
        micro.Name("second"),
        micro.Registry(consul.NewRegistry(registry.Addrs("49.234.57.x:8500"))),
    )
    service.Init()
    firstCli := pb.NewFirstService("first", service.Client())
    go func() {
        time.Sleep(1*time.Second)
        obj := &pb.Response{}
        data, err := firstCli.Hello(context.Background(), &pb.Request{})
        if err != nil {
             fmt.Println(err)
        } else {
            types.UnmarshalAny(data.GetData(), obj)
            fmt.Println(obj)
        }
    }
    service.Run()
}

Test:

  1. If the first/second server deployed on the same cloud pc, the second server can get data from the first server by rpc.
  2. If the first/second server deployed on different cloud pc(Both pc have access to all ports), I will get error:
    {"id":"go.micro.client","code":408,"detail":"call timeout: context deadline exceeded","status":"Request Timeout"}","time":"x"}

the second service(ip: 52.81.x.x) can get data from the first server(ip: 49.234.57.x) by extranet ip reg consul?

plugins/v4/config/source/configmap list/watch error

When I use ConfigMap as my config plugin, I found that the REST client for List/Watch is missing the GroupVersion information.

my configmap code is

err := config.DefaultConfig.Load(configmap.NewSource(configmap.WithName("auth-config"), configmap.WithNamespace("yunhang"), configmap.WithConfigPath("~/.kube/config")))

and the error log is

W0324 16:05:11.020136   88445 reflector.go:424] pkg/mod/k8s.io/[email protected]/tools/cache/reflector.go:169: failed to list *v1.ConfigMap: the server could not find the requested resource (get configmaps.meta.k8s.io)
E0324 16:05:11.020164   88445 reflector.go:140] pkg/mod/k8s.io/[email protected]/tools/cache/reflector.go:169: Failed to watch *v1.ConfigMap: failed to list *v1.ConfigMap: the server could not find the requested resource (get configmaps.meta.k8s.io)

and than i found list/watch url is

https://kubernetes.docker.internal:6443/namespaces/yunhang/configmaps

the correct url should be that.(miss api/v1)

https://kubernetes.docker.internal:6443/api/v1/namespaces/yunhang/configmaps

https://github.com/go-micro/plugins/blob/0bbab425e86658eeb7b55602f184d37c1ea75094/v4/config/source/configmap/watcher.go#L38
I think the code might be like that, or do you have any better ideas?

 lw := cache.NewListWatchFromClient(w.client.CoreV1().RESTClient(), "configmaps", w.namespace, fields.OneTermEqualSelector("metadata.name", w.name))

[BUG] v4/server/grpc - Broker address is logged raw, potentially exposing credentials in logs

Describe the bug

  1. What are you trying to do?
    Utilize go-micro v4 with the grpc server/rabbitmq broker plugins, connecting to a broker authenticated with a username/password.

  2. What did you expect to happen?
    When the framework logs the broker address upon connection / disconnection, either the address should be omitted, or any embedded credentials should be redacted.

  3. What happens instead?
    The full address is logged upon connect / disconnect, as shown in the example below:

Broker [rabbitmq] Connected to amqp://<username>:<password>@localhost:5672

How to reproduce the bug:
Setup a broker with an address that embeds credentials, seems like the lines in question can be found here:

https://github.com/go-micro/plugins/blob/0ed40ba1aacebe0d38d871a6272f78125bf68dbc/v4/server/grpc/grpc.go#L910-L912

https://github.com/go-micro/plugins/blob/0ed40ba1aacebe0d38d871a6272f78125bf68dbc/v4/server/grpc/grpc.go#L1015-L1017

Environment:
Go Version: please paste go version output here

GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/davidbereza/Library/Caches/go-build"
GOENV="/Users/davidbereza/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/davidbereza/go/pkg/mod"
GONOPROXY="github.com/vlognow/*"
GONOSUMDB="github.com/vlognow/*"
GOOS="darwin"
GOPATH="/Users/davidbereza/go"
GOPRIVATE="github.com/vlognow/*"
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/opt/homebrew/Cellar/go/1.18.4/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/opt/homebrew/Cellar/go/1.18.4/libexec/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.18.4"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/s_/p4h9rj3d2h3gjsw4ngyvb2kw0000gn/T/go-build1917015884=/tmp/go-build -gno-record-gcc-switches -fno-common"

package "go-micro.dev/v4/cmd" unavailable yet

package "go-micro.dev/v4/cmd" removed from latest version of go-micro

imported in:

v4/cache/redis/redis.go: "go-micro.dev/v4/cmd"
v4/client/grpc/grpc.go: "go-micro.dev/v4/cmd"
v4/client/http/http.go: "go-micro.dev/v4/cmd"
v4/client/mucp/mucp.go: "go-micro.dev/v4/cmd"
v4/transport/quic/quic.go: "go-micro.dev/v4/cmd"
v4/transport/utp/utp.go: "go-micro.dev/v4/cmd"
v4/transport/memory/memory.go: "go-micro.dev/v4/cmd"
v4/transport/rabbitmq/rabbitmq.go: "go-micro.dev/v4/cmd"
v4/transport/grpc/grpc.go: "go-micro.dev/v4/cmd"
v4/transport/tcp/tcp.go: "go-micro.dev/v4/cmd"
v4/transport/nats/nats.go: "go-micro.dev/v4/cmd"
v4/server/grpc/grpc.go: "go-micro.dev/v4/cmd"
v4/server/http/http.go: "go-micro.dev/v4/cmd"
v4/server/mucp/mucp.go: "go-micro.dev/v4/cmd"
v4/broker/sqs/sqs.go: "go-micro.dev/v4/cmd"
v4/broker/snssqs/snssqs.go: "go-micro.dev/v4/cmd"
v4/broker/memory/memory.go: "go-micro.dev/v4/cmd"
v4/broker/googlepubsub/googlepubsub.go: "go-micro.dev/v4/cmd"
v4/broker/rabbitmq/rabbitmq.go: "go-micro.dev/v4/cmd"
v4/broker/stomp/stomp.go: "go-micro.dev/v4/cmd"
v4/broker/stan/stan.go: "go-micro.dev/v4/cmd"
v4/broker/grpc/grpc.go: "go-micro.dev/v4/cmd"
v4/broker/http/http.go: "go-micro.dev/v4/cmd"
v4/broker/nsq/nsq.go: "go-micro.dev/v4/cmd"
v4/broker/proxy/proxy.go: "go-micro.dev/v4/cmd"
v4/broker/segmentio/segmentio.go: "go-micro.dev/v4/cmd"
v4/broker/redis/redis.go: "go-micro.dev/v4/cmd"
v4/broker/kafka/kafka.go: "go-micro.dev/v4/cmd"
v4/broker/gocloud/gocloud.go: "go-micro.dev/v4/cmd"
v4/broker/mqtt/mqtt.go: "go-micro.dev/v4/cmd"
v4/broker/nats/nats.go: "go-micro.dev/v4/cmd"
v4/auth/jwt/jwt.go: "go-micro.dev/v4/cmd"
v4/store/cockroach/cockroach.go: "go-micro.dev/v4/cmd"
v4/store/mysql/mysql.go: "go-micro.dev/v4/cmd"
v4/store/file/file.go: "go-micro.dev/v4/cmd"
v4/store/memory/memory.go: "go-micro.dev/v4/cmd"
v4/store/nats-js/nats.go: "go-micro.dev/v4/cmd"
v4/store/memcached/memcached.go: "go-micro.dev/v4/cmd"
v4/store/consul/consul.go: "go-micro.dev/v4/cmd"
v4/store/redis/redis.go: "go-micro.dev/v4/cmd"
v4/registry/etcd/etcd.go: "go-micro.dev/v4/cmd"
v4/registry/mdns/mdns.go: "go-micro.dev/v4/cmd"
v4/registry/gossip/gossip.go: "go-micro.dev/v4/cmd"
v4/registry/eureka/eureka.go: "go-micro.dev/v4/cmd"
v4/registry/proxy/proxy.go: "go-micro.dev/v4/cmd"
v4/registry/nacos/nacos.go: "go-micro.dev/v4/cmd"
v4/registry/consul/consul.go: "go-micro.dev/v4/cmd"
v4/registry/kubernetes/kubernetes.go: "go-micro.dev/v4/cmd"
v4/registry/zookeeper/zookeeper.go: "go-micro.dev/v4/cmd"
v4/registry/nats/nats.go: "go-micro.dev/v4/cmd"
v4/selector/static/static.go: "go-micro.dev/v4/cmd"
v4/selector/registry/registry.go: "go-micro.dev/v4/cmd"
v4/selector/label/label.go: "go-micro.dev/v4/cmd"
v4/config/source/mucp/mucp.go: "go-micro.dev/v4/cmd"

[BUG] Issues with store plugin redis

Describe the bug

In github.com/asim/go-micro/plugins/store/redis/v4 package :

  • List doesn't filter by table (ListFrom) . Also doesn't remove the table prefix in the return.
  • Read with ReadPrefix option doesn't fill the keys

How to reproduce the bug:

package main

import (
	"reflect"
	"testing"

	redisStore "github.com/asim/go-micro/plugins/store/redis/v4"
	"go-micro.dev/v4/store"
)

func init() {
	store.DefaultStore = redisStore.NewStore(store.Nodes("redis://redis:6379"))
}

func Test_store(t *testing.T) {
	store.DefaultStore.Write(
		&store.Record{Key: "key1", Value: []byte("val1")},
		store.WriteTo("", "table-a"),
	)
	store.DefaultStore.Write(
		&store.Record{Key: "key2", Value: []byte("val2")},
		store.WriteTo("", "table-b"),
	)
	store.DefaultStore.Write(
		&store.Record{Key: "key3", Value: []byte("val3")},
		store.WriteTo("", "table-a"),
	)

	gotList, _ := store.DefaultStore.List(store.ListFrom("", "table-a"))
	wantList := []string{"key1"}
	if !reflect.DeepEqual(gotList, wantList) {
		t.Errorf("DefaultStore.List() = %#v; want %#v", gotList, wantList)
	}

	gotRead, _ := store.DefaultStore.Read("", store.ReadFrom("", "table-a"), store.ReadPrefix())
	wantRead := []*store.Record{
		{Key: "key3", Value: []byte("val3"), Expiry: -1},
		{Key: "key1", Value: []byte("val1"), Expiry: -1},
	}
	if !reflect.DeepEqual(gotRead, wantRead) {
		t.Errorf("DefaultStore.Read() = %#v; want %#v", gotRead, wantRead)
		t.Errorf("DefaultStore.Read()[0] = %#v; want %#v", gotRead[0], wantRead[0])
		t.Errorf("DefaultStore.Read()[1] = %#v; want %#v", gotRead[1], wantRead[1])
	}

	gotRead, _ = store.DefaultStore.Read("key1", store.ReadFrom("", "table-a"))
	wantRead = []*store.Record{
		{Key: "key1", Value: []byte("val1"), Expiry: -1},
	}
	if !reflect.DeepEqual(gotRead, wantRead) {
		t.Errorf("DefaultStore.Read() = %#v; want %#v", gotRead, wantRead)
		t.Errorf("DefaultStore.Read()[0] = %#v; want %#v", gotRead[0], wantRead[0])
	}
}

Returns:

=== RUN   Test_store
    store_test.go:32: DefaultStore.List() = []string{"table-akey3", "table-bkey2", "table-akey1"}; want []string{"key1"}
    store_test.go:41: DefaultStore.Read() = []*store.Record{(*store.Record)(0xc000150000), (*store.Record)(0xc00007a000)}; want []*store.Record{(*store.Record)(0xc00007a040), (*store.Record)(0xc00007a080)}
    store_test.go:42: DefaultStore.Read()[0] = &store.Record{Key:"", Value:[]uint8{0x76, 0x61, 0x6c, 0x33}, Metadata:map[string]interface {}(nil), Expiry:-1}; want &store.Record{Key:"key3", Value:[]uint8{0x76, 0x61, 0x6c, 0x33}, Metadata:map[string]interface {}(nil), Expiry:-1}
    store_test.go:43: DefaultStore.Read()[1] = &store.Record{Key:"", Value:[]uint8{0x76, 0x61, 0x6c, 0x31}, Metadata:map[string]interface {}(nil), Expiry:-1}; want &store.Record{Key:"key1", Value:[]uint8{0x76, 0x61, 0x6c, 0x31}, Metadata:map[string]interface {}(nil), Expiry:-1}
--- FAIL: Test_store (0.06s)

Environment:

go version go1.16.14 linux/amd64

GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.16.14"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/workspace/data_management/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2927763455=/tmp/go-build -gno-record-gcc-switches"

nacos can not work

Before asking, please check if your question has already been answered:

service := micro.NewService(
		micro.Server(srv),
		micro.Registry(nacos.NewRegistry(registry.Addrs("192.168.144.17:8888"))),
	)

I have set addr 192.168.144.17:8888

BUT still
Try to connect to server on start up, server: {serverIp:127.0.0.1 serverPort:8848}

error message:

2022-01-25T12:22:20.516+0800	�[34mINFO�[0m	Local IP:192.168.144.17
2022-01-25T12:22:22.502+0800	�[33mWARN�[0m	[RpcClient.Start] 5c6b766a-ca55-4798-9f7c-608f93b64ad6 Fail to connect to server on start up, error message=rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp 127.0.0.1:9848: connectex: No connection could be made because the target machine actively refused it.", start up retry times left=2
2022-01-25T12:22:22.502+0800	�[34mINFO�[0m	[RpcClient.Start] 5c6b766a-ca55-4798-9f7c-608f93b64ad6 Try to connect to server on start up, server: {serverIp:127.0.0.1 serverPort:8848}
2022-01-25T12:22:24.515+0800	�[33mWARN�[0m	[RpcClient.Start] 5c6b766a-ca55-4798-9f7c-608f93b64ad6 Fail to connect to server on start up, error message=rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp 127.0.0.1:9848: connectex: No connection could be made because the target machine actively refused it.", start up retry times left=1
2022-01-25T12:22:24.515+0800	�[34mINFO�[0m	[RpcClient.Start] 5c6b766a-ca55-4798-9f7c-608f93b64ad6 Try to connect to server on start up, server: {serverIp:127.0.0.1 serverPort:8848}
2022-01-25T12:22:26.517+0800	�[33mWARN�[0m	[RpcClient.Start] 5c6b766a-ca55-4798-9f7c-608f93b64ad6 Fail to connect to server on start up, error message=rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp 127.0.0.1:9848: connectex: No connection could be made because the target machine actively refused it.", start up retry times left=0
2022-01-25T12:22:26.517+0800	�[34mINFO�[0m	5c6b766a-ca55-4798-9f7c-608f93b64ad6 Register server push request:NotifySubscriberRequest handler:&{ServiceInfoHolder:0xc000086300}
2022-01-25T12:22:26.517+0800	�[34mINFO�[0m	5c6b766a-ca55-4798-9f7c-608f93b64ad6 try to re connect to a new server ,server is  not appointed,will choose a random server.
2022-01-25T12:22:26.517+0800	�[34mINFO�[0m	5c6b766a-ca55-4798-9f7c-608f93b64ad6 Register connection listener [&{clientProxy:0xc000490140 registeredInstanceCached:[0xc0000bcf20 0xc0000bcf40 0xc0000bcf60 0xc0000bcf80 0xc0000bcfa0 0xc0000bcfc0 0xc0000bcfe0 0xc0000bd000 0xc0000bd020 0xc0000bd040 0xc0000bd060 0xc0000bd080 0xc0000bd0a0 0xc0000bd0c0 0xc0000bd0e0 0xc0000bd100 0xc0000bd120 0xc0000bd140 0xc0000bd160 0xc0000bd180 0xc0000bd1a0 0xc0000bd1c0 0xc0000bd1e0 0xc0000bd200 0xc0000bd220 0xc0000bd240 0xc0000bd260 0xc0000bd280 0xc0000bd2a0 0xc0000bd2c0 0xc0000bd2e0 0xc0000bd300] subscribes:[0xc0000bd320 0xc0000bd340 0xc0000bd360 0xc0000bd380 0xc0000bd3a0 0xc0000bd3c0 0xc0000bd3e0 0xc0000bd400 0xc0000bd420 0xc0000bd440 0xc0000bd460 0xc0000bd480 0xc0000bd4a0 0xc0000bd4c0 0xc0000bd4e0 0xc0000bd500 0xc0000bd520 0xc0000bd540 0xc0000bd560 0xc0000bd580 0xc0000bd5a0 0xc0000bd5c0 0xc0000bd5e0 0xc0000bd600 0xc0000bd620 0xc0000bd640 0xc0000bd660 0xc0000bd680 0xc0000bd6a0 0xc0000bd6c0 0xc0000bd6e0 0xc0000bd700]}] to current client
2022-01-25T12:22:26.518+0800	�[31mERROR�[0m	Send request fail, request=&{NamingRequest:0xc0000700a0 Clusters: HealthyOnly:false UdpPort:0}, retryTimes=0xc00002a050,error=Client not connected,current status:1
2022-01-25T12:22:26.535+0800	�[34mINFO�[0m	register instance namespaceId:<public>,serviceName:<helloworld> with instance:<{"instanceId":"","ip":"192.168.144.17","port":80,"weight":1,"healthy":true,"enabled":true,"ephemeral":true,"clusterName":"","serviceName":"","metadata":{"broker":"http","protocol":"http","registry":"nacos","server":"http","version":"latest"},"instanceHeartBeatInterval":0,"ipDeleteTimeout":0,"instanceHeartBeatTimeOut":0}>
2022-01-25T12:22:26.535+0800	�[31mERROR�[0m	Send request fail, request=&{NamingRequest:0xc0003e0320 Type:registerInstance Instance:{InstanceId: Ip:192.168.144.17 Port:80 Weight:1 Healthy:true Enable:true Ephemeral:true ClusterName: ServiceName: Metadata:map[broker:http protocol:http registry:nacos server:http version:latest] InstanceHeartBeatInterval:0 IpDeleteTimeout:0 InstanceHeartBeatTimeOut:0}}, retryTimes=0xc0000ab220,error=Client not connected,current status:1
2022-01-25T12:22:26.618+0800	�[31mERROR�[0m	Send request fail, request=&{NamingRequest:0xc0000700a0 Clusters: HealthyOnly:false UdpPort:0}, retryTimes=0xc00002a050,error=Client not connected,current status:1
2022-01-25T12:22:26.636+0800	�[31mERROR�[0m	Send request fail, request=&{NamingRequest:0xc0003e0320 Type:registerInstance Instance:{InstanceId: Ip:192.168.144.17 Port:80 Weight:1 Healthy:true Enable:true Ephemeral:true ClusterName: ServiceName: Metadata:map[broker:http protocol:http registry:nacos server:http version:latest] InstanceHeartBeatInterval:0 IpDeleteTimeout:0 InstanceHeartBeatTimeOut:0}}, retryTimes=0xc0000ab220,error=Client not connected,current status:1
2022-01-25T12:22:26.719+0800	�[31mERROR�[0m	Send request fail, request=&{NamingRequest:0xc0000700a0 Clusters: HealthyOnly:false UdpPort:0}, retryTimes=0xc00002a050,error=Client not connected,current status:1
2022-01-25T12:22:26.737+0800	�[31mERROR�[0m	Send request fail, request=&{NamingRequest:0xc0003e0320 Type:registerInstance Instance:{InstanceId: Ip:192.168.144.17 Port:80 Weight:1 Healthy:true Enable:true Ephemeral:true ClusterName: ServiceName: Metadata:map[broker:http protocol:http registry:nacos server:http version:latest] InstanceHeartBeatInterval:0 IpDeleteTimeout:0 InstanceHeartBeatTimeOut:0}}, retryTimes=0xc0000ab220,error=Client not connected,current status:1
2022-01-25T12:22:26.820+0800	�[31mERROR�[0m	QueryList return error!serviceName:helloworld cluster: err:Client not connected,current status:1

plugins/client/grpc Cannot be used according to Usage

go: finding module for package github.com/micro/go-plugins/client/grpc
api/logics imports
github.com/micro/go-plugins/client/grpc: module github.com/micro/go-plugins@latest found (v1.5.1), but does not contain package github.com/micro/go-plugins/client/grpc

TCP transport race condition

WARNING: DATA RACE
Read at 0x00c0008508a8 by goroutine 142813:
  bufio.(*Writer).Available()
      /usr/lib/go/src/bufio/bufio.go:646 +0xef
  bufio.(*Writer).Write()
      /usr/lib/go/src/bufio/bufio.go:664 +0x26
  encoding/gob.(*Encoder).writeMessage()
      /usr/lib/go/src/encoding/gob/encoder.go:82 +0x774
  encoding/gob.(*Encoder).EncodeValue()
      /usr/lib/go/src/encoding/gob/encoder.go:253 +0x84a
  encoding/gob.(*Encoder).Encode()
      /usr/lib/go/src/encoding/gob/encoder.go:176 +0x15a
  github.com/go-micro/plugins/v4/transport/tcp.(*tcpTransportSocket).Send()
      /home/tyler/go/pkg/mod/github.com/go-micro/plugins/v4/transport/[email protected]/tcp.go:107 +0xfe
  go-micro.dev/v4/server.(*rpcServer).ServeConn.func3()
      /home/tyler/Launchpad/Micro/go-micro/server/rpc_server.go:353 +0x487
  go-micro.dev/v4/server.(*rpcServer).ServeConn.func5()
      /home/tyler/Launchpad/Micro/go-micro/server/rpc_server.go:357 +0x47

Previous write at 0x00c0008508a8 by goroutine 142778:
  bufio.(*Writer).Flush()
      /usr/lib/go/src/bufio/bufio.go:641 +0x328
  github.com/go-micro/plugins/v4/transport/tcp.(*tcpTransportSocket).Send()
      /home/tyler/go/pkg/mod/github.com/go-micro/plugins/v4/transport/[email protected]/tcp.go:110 +0x146
  go-micro.dev/v4/server.(*rpcServer).ServeConn.func3()
      /home/tyler/Launchpad/Micro/go-micro/server/rpc_server.go:353 +0x487
  go-micro.dev/v4/server.(*rpcServer).ServeConn.func5()
      /home/tyler/Launchpad/Micro/go-micro/server/rpc_server.go:357 +0x47

Goroutine 142813 (running) created at:
  go-micro.dev/v4/server.(*rpcServer).ServeConn()
      /home/tyler/Launchpad/Micro/go-micro/server/rpc_server.go:325 +0x205b
  go-micro.dev/v4/server.(*rpcServer).ServeConn-fm()
      <autogenerated>:1 +0x4d
  github.com/go-micro/plugins/v4/transport/tcp.(*tcpTransportListener).Accept.func1()
      /home/tyler/go/pkg/mod/github.com/go-micro/plugins/v4/transport/[email protected]/tcp.go:164 +0x81

Goroutine 142778 (finished) created at:
  go-micro.dev/v4/server.(*rpcServer).ServeConn()
      /home/tyler/Launchpad/Micro/go-micro/server/rpc_server.go:325 +0x205b
  go-micro.dev/v4/server.(*rpcServer).ServeConn-fm()
      <autogenerated>:1 +0x4d
  github.com/go-micro/plugins/v4/transport/tcp.(*tcpTransportListener).Accept.func1()
      /home/tyler/go/pkg/mod/github.com/go-micro/plugins/v4/transport/[email protected]/tcp.go:164 +0x81

Wrong returning value

The injectTraceIntoCtx function is supposed to inject the trace into the context. But instead of that it just returns with the same context.
https://github.com/go-micro/plugins/blob/1d6f7b8f9464faf5ece160503ce3478c87e0af85/v2/wrapper/trace/opencensus/opencensus.go#L28-L32

The metadata.Set function returns with the new context not modifying the parameter
https://github.com/asim/go-micro/blob/master/metadata/metadata.go#L54-L65

I think this is how it is supposed to be:

ctx = metadata.Set(ctx, TracePropagationField, base64.RawStdEncoding.EncodeToString(spanCtx))

With this change, the trace is sent between the microservices and I can see them in Jaeger:
Screen Shot 2022-05-26 at 2 20 48 PM

Without the change:
Screen Shot 2022-05-26 at 2 21 05 PM

Cannot import plugins/v4/server/grpc

When importing plugins/v4/server/grpc, I get following message:

go: finding module for package github.com/go-micro/plugins/v4/client/grpc/v4
go: finding module for package github.com/go-micro/plugins/v4/server/grpc
go: found github.com/go-micro/plugins/v4/server/grpc in github.com/go-micro/plugins/v4/server/grpc v1.0.0
go: downloading github.com/go-micro/plugins/v4/transport/grpc v0.0.0
github.com/owncloud/ocis/ocis-pkg/service/grpc imports
	github.com/go-micro/plugins/v4/server/grpc tested by
	github.com/go-micro/plugins/v4/server/grpc.test imports
	github.com/go-micro/plugins/v4/transport/grpc: reading github.com/go-micro/plugins/v4/transport/grpc/v4/transport/grpc/go.mod at revision v4/transport/grpc/v0.0.0: unknown revision v4/transport/grpc/v0.0.0

This is because of these lines:

https://github.com/go-micro/plugins/blob/254c7a4afab66cf0ba0db6dfe8519e468e603107/v4/server/grpc/go.mod#L6-L7

Ideally, they should also point to v1.0.0 (the most recent version) but I don't know how that fit's in the release process!? Do you plan to always tag all plugins at the same time or will they get separate releases? If the second option is the case, we should be able to fix it once and then get Dependabot / RenovateBot PRs to update the transport plugin automatically after a release.

CC @xpunch

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.