Golang with couchbase integration issue - go

I'm using golang with couchbase integration component called go-couchbase. It's enable to connect with couchbase and retrieve data. However I have a problem to send start key and skip value and limit value with this API. Because there is no functionality found by myself.
url : - github.com/couchbaselabs/go-couchbase
Please let me know any method to send these values to couchbase and retrieve data?

That start key is only mentioned once, as a parameter to a couhbase view:
// View executes a view.
//
// The ddoc parameter is just the bare name of your design doc without
// the "_design/" prefix.
//
// Parameters are string keys with values that correspond to couchbase
// view parameters. Primitive should work fairly naturally (booleans,
// ints, strings, etc...) and other values will attempt to be JSON
// marshaled (useful for array indexing on on view keys, for example).
//
// Example:
//
// res, err := couchbase.View("myddoc", "myview", map[string]interface{}{
// "group_level": 2,
// "start_key": []interface{}{"thing"},
// "end_key": []interface{}{"thing", map[string]string{}},
// "stale": false,
// })
func (b *Bucket) View(ddoc, name string, params map[string]interface{}) (ViewResult, error) {
I suppose the skip one (mentioned in "Pagination with Couchbase") is just another parameter to add to the params map[string]interface{}.

Related

How does a value in Go context get marshalled when the context is passed over to a remote service?

Below is the signature of the WithValue func.
func WithValue(parent Context, key, val interface{}) Context
I took a look at Go official documentation but they didn't mention how a value would get marshalled when the context is passed over to a remote service.
For example, I can pass in anything as val such as a complex struct containing exported and un-exported fields. I wonder if my un-exported fields would ever reach the remote service. If they do, how does it work behind the scene? The whole context object gets marshalled into []byte regardless of fields?
One concrete sample of a complex object is the internal implementation of a Span in opentracing.
// Implements the `Span` interface. Created via tracerImpl (see
// `basictracer.New()`).
type spanImpl struct {
tracer *tracerImpl
event func(SpanEvent)
sync.Mutex // protects the fields below
raw RawSpan
// The number of logs dropped because of MaxLogsPerSpan.
numDroppedLogs int
}
The above Span can be passed around from service to service by creating a derived context using the func below.
// ContextWithSpan returns a new `context.Context` that holds a reference to
// the span. If span is nil, a new context without an active span is returned.
func ContextWithSpan(ctx context.Context, span Span) context.Context {
if span != nil {
if tracerWithHook, ok := span.Tracer().(TracerContextWithSpanExtension); ok {
ctx = tracerWithHook.ContextWithSpanHook(ctx, span)
}
}
return context.WithValue(ctx, activeSpanKey, span)
}
What is the high-level protocols/rules that Go uses to pass around complex values stored in Go context? Would the func(SpanEvent) and the mutex really travel over the wire to the next service?
I'd be very grateful if you could explain the expected behavior or point me in the direction of some articles I've not found.

Calling type function for a member of map

I'm coding a communication protocol. It sends tokens, which I need to use to authenticate.
I have created a type, "AuthToken" that encodes/decodes the token for me.
In the package "utils", I declare it and some of the functions like this (this is like a pseudo-code):
package utils
type AuthToken struct{
// vars
}
func (token *AuthToken) Decode(encoded string){
// Decodes the token and fills internal fields
}
func (token AuthToken) GetField() string{
return field
}
In my main package, I want to create a map of AuthTokens to store them, but I can't use the function Decode in a member of the map, while I can use GetField:
package main
type TokenList map[string]utils.AuthToken
func main(){
tokenList := make(TokenList)
// To init one member I do:
tokenList["1"] = utils.AuthToken{} // This works
tokenList["2"] = make(utils.AuthToken) // This doesn't
// Then I need to call the function above, so I tried:
tokenList["1"].Decode("encoded") // Returns cannot call pointer method
I have tried searching for it, but either I don't know where to search, or there is no info about how to do this.
tokenList["2"] = make(utils.AuthToken) // This doesn't
You cannot use make keyword to instantiate an object from struct. That's the reason why above statement wont work.
tokenList["1"] = utils.AuthToken{}
tokenList["1"].Decode("encoded") // Returns cannot call pointer method
The tokenList["1"] returns non pointer object. You will need to store it into a variable, then from there do access the pointer, only then you will be able to call .Decode() method.
obj := tokenList["1"]
objPointer := &obj
objPointer.Decode("encoded")

List custom resources from caching client with custom fieldSelector

I'm using the Operator SDK to build a custom Kubernetes operator. I have created a custom resource definition and a controller using the respective Operator SDK commands:
operator-sdk add api --api-version example.com/v1alpha1 --kind=Example
operator-sdk add controller --api-version example.com/v1alpha1 --kind=Example
Within the main reconciliation loop (for the example above, the auto-generated ReconcileExample.Reconcile method) I have some custom business logic that requires me to query the Kubernetes API for other objects of the same kind that have a certain field value. It's occurred to me that I might be able to use the default API client (that is provided by the controller) with a custom field selector:
func (r *ReconcileExample) Reconcile(request reconcile.Request) (reconcile.Result, error) {
ctx := context.TODO()
listOptions := client.ListOptions{
FieldSelector: fields.SelectorFromSet(fields.Set{"spec.someField": "someValue"}),
Namespace: request.Namespace,
}
otherExamples := v1alpha1.ExampleList{}
if err := r.client.List(ctx, &listOptions, &otherExamples); err != nil {
return reconcile.Result{}, err
}
// do stuff...
return reconcile.Result{}, nil
}
When I run the operator and create a new Example resource, the operator fails with the following error message:
{"level":"info","ts":1563388786.825384,"logger":"controller_example","msg":"Reconciling Example","Request.Namespace":"default","Request.Name":"example-test"}
{"level":"error","ts":1563388786.8255732,"logger":"kubebuilder.controller","msg":"Reconciler error","controller":"example-controller","request":"default/example-test","error":"Index with name field:spec.someField does not exist","stacktrace":"..."}
The most important part being
Index with name field:spec.someField does not exist
I've already searched the Operator SDK's documentation on the default API client and learned a bit about the inner workings of the client, but no detailed explanation on this error or how to fix it.
What does this error message mean, and how can I create this missing index to efficiently list objects by this field value?
The default API client that is provided by the controller is a split client -- it serves Get and List requests from a locally-held cache and forwards other methods like Create and Update directly to the Kubernetes API server. This is also explained in the respective documentation:
The SDK will generate code to create a Manager, which holds a Cache and a Client to be used in CRUD operations and communicate with the API server. By default a Controller's Reconciler will be populated with the Manager's Client which is a split-client. [...] A split client reads (Get and List) from the Cache and writes (Create, Update, Delete) to the API server. Reading from the Cache significantly reduces request load on the API server; as long as the Cache is updated by the API server, read operations are eventually consistent.
To query values from the cache using a custom field selector, the cache needs to have a search index for this field. This indexer can be defined right after the cache has been set up.
To register a custom indexer, add the following code into the bootstrapping logic of the operator (in the auto-generated code, this is done directly in main). This needs to be done after the controller manager has been instantiated (manager.New) and also after the custom API types have been added to the runtime.Scheme:
package main
import (
k8sruntime "k8s.io/apimachinery/pkg/runtime"
"example.com/example-operator/pkg/apis/example/v1alpha1"
// ...
)
function main() {
// ...
cache := mgr.GetCache()
indexFunc := func(obj k8sruntime.Object) []string {
return []string{obj.(*v1alpha1.Example).Spec.SomeField}
}
if err := cache.IndexField(&v1alpha1.Example{}, "spec.someField", indexFunc); err != nil {
panic(err)
}
// ...
}
When a respective indexer function is defined, field selectors on spec.someField will work from the local cache as expected.

Unable to set query parameters manually for a rest api (using mux)

I am implementing a Rest api using mux. After validating some parameters, I am trying to fill the missing parameters with some default values which I process later by the method that handles the request, however, I noticed that setting query parameters manually does not have any effect, unless the raw query is directly changed which is a bit hacky:
func ValidateParameters(r *http.Request) (bool) {
test := r.URL.Query().Get("test")
// if test is not provided set some default value
if test == "" {
r.URL.Query().Set("test", "Test1") //not working
r.URL.Query().Add("test", "Test2") //not working
r.URL.RawQuery = r.URL.RawQuery + "&Test=Test3" // the only method working
}
// more code
}
The handler is in another file, so I want to be able to do test := r.URL.Query().Get("test") and get the value that I set inside ValidateParameters which is called by the request handler, but this is not working.
any explanation to that ? any way to work around it ?
Thanks.
The problem is that r.URL.Query() parses the url, creates the map of parameters and returns it. This is done with every .Query() call.
This should work:
params := r.URL.Query()
params.Set("key", "value")
r.URL.RawQuery = params.Encode()

Google Datastore go client, storing dynamic data

Our application provides functionality which enables a customer to create dynamic forms and business rules. We recently decided to explore Google infrastructures so we don't have to spend time tweaking and adjusting our infrastructure.
Thus far, we have managed well using a NOSQL database such as arangodb to store random data sets through their JSON HTTP REST APIs, that stores any sort of data structure, so long as it is a valid JSON. However, Google data store go client library and Datastore doesn;t work with JSON and also imposes rules like no silce []type, no map map[type]type failing with errors such as datastore: invalid Value type e.t.c
I explored option of implementing PropertyLoadSaver interface load/save functions with modifications to create PropertyList and Property to crate a []Property. Case below Collection is type Collection map[string]interface{} which holds an sort of data set
func (m Collection) Save() ([]datastore.Property, error) {
data := []datastore.Property{}
for key, value := range m {
if util.IsSlice(value) {
props := datastore.PropertyList{}
for _, item := range value.([]string) {
props = append(props, datastore.Property{Name: key, Value: item})
}
data = append(data, datastore.Property{Name: key, Value: props})
} else {
data = append(data, datastore.Property{Name: key, Value: value, NoIndex: true})
}
}
json.NewEncoder(os.Stdout).Encode(data)
return data, nil
}
Yes, we can create a struct which we can populate based on map data and save that to Datastore. We were however wondering if there possibly is an easier way to just receive a map and save it to Datastore with no added complexity.
Alternative
type Person struct{
Name string
Surname string
Addresses []Address
...
}
type Address struct{
Type string
Detail string
}
This map[string]interface{}{Name:"Kwasi", Surname:"Gyasi-Agyei", Addresses:...} can than be marshaled into above struct to be saved by Datastore go client lib.
Am however more interested in taking advantage of PropertList, []Property, unless that route is unnecessarily complex. What am basically asking is, which is the most appropriate route that offer the same type of flexibility as a schemaless database.

Resources