How to use kubernetes go-client on amazon eks service? - go

I've been looking for documentation for a long time and still couldn't find any clear connection procedure.
I came up with this code sample :
package aws
import (
"fmt"
"net/http"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/eks"
"github.com/joho/godotenv"
)
func Connect() {
godotenv.Load(".env")
session := session.Must(session.NewSession())
svc := eks.New(session)
clusters, err := svc.ListClusters(&eks.ListClustersInput{})
if err != nil {
fmt.Println(err.Error())
}
fmt.Println(clusters)
}
i mean, this still returns a 403 forbidden error because of env variable mess, but the code is valid i guess. My question is, having this connection established : how to convert this svc variable into the *kubernetes.Clientset one from the go driver ?

Have you had a look at the client-go example on how to authenticate in-cluster?
Code that authenticate to the Kubernetes API typically start like this:
// creates the in-cluster config
config, err := rest.InClusterConfig()
if err != nil {
panic(err.Error())
}
// creates the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}

I use the following code to automatically detect where its running from local machine or any kubernetes cluster.
var config *rest.Config
if _, err := os.Stat("/var/run/secrets/kubernetes.io/serviceaccount/token"); err == nil {
config, err = rest.InClusterConfig()
if err != nil {
log.Fatal(err)
}
} else if os.IsNotExist(err) {
config, err = clientcmd.BuildConfigFromFlags("", *kubeConfig)
if err != nil {
log.Fatal("No serviceaccount mounted or -kubeconfig flag passed or .kube/config file \n " ,err)
}
}
// Create an rest client not targeting specific API version
clientSet, err := kubernetes.NewForConfig(config)
if err != nil {
log.Fatal(err)
}

Related

Google Cloud Vertex AI with Golang: rpc error: code = Unimplemented desc = unexpected HTTP status code received from server: 404 (Not Found)

I have a Vertex AI model deployed on an endpoint and want to do some prediction from my app in Golang.
To do this I create code inspired by this example : https://cloud.google.com/go/docs/reference/cloud.google.com/go/aiplatform/latest/apiv1?hl=en
const file = "MY_BASE64_IMAGE"
func main() {
ctx := context.Background()
c, err := aiplatform.NewPredictionClient(cox)
if err != nil {
log.Printf("QueryVertex NewPredictionClient - Err:%s", err)
}
defer c.Close()
parameters, err := structpb.NewValue(map[string]interface{}{
"confidenceThreshold": 0.2,
"maxPredictions": 5,
})
if err != nil {
log.Printf("QueryVertex structpb.NewValue parameters - Err:%s", err)
}
instance, err := structpb.NewValue(map[string]interface{}{
"content": file,
})
if err != nil {
log.Printf("QueryVertex structpb.NewValue instance - Err:%s", err)
}
reqP := &aiplatformpb.PredictRequest{
Endpoint: "projects/PROJECT_ID/locations/LOCATION_ID/endpoints/ENDPOINT_ID",
Instances: []*structpb.Value{instance},
Parameters: parameters,
}
resp, err := c.Predict(cox, reqP)
if err != nil {
log.Printf("QueryVertex Predict - Err:%s", err)
}
log.Printf("QueryVertex Res:%+v", resp)
}
I put the path to my service account JSON file on GOOGLE_APPLICATION_CREDENTIALS environment variable.
But when I run my test app I obtain this error message:
QueryVertex Predict - Err:rpc error: code = Unimplemented desc = unexpected HTTP status code received from server: 404 (Not Found); transport: received unexpected content-type "text/html; charset=UTF-8"
QueryVertex Res:<nil>
As #DazWilkin suggested, configure the client option to specify the specific regional endpoint with a port 443:
option.WithEndpoint("<region>-aiplatform.googleapis.com:443")
Try like below:
func main() {
ctx := context.Background()
c, err := aiplatform.NewPredictionClient(
ctx,
option.WithEndpoint("<region>-aiplatform.googleapis.com:443"),
)
if err != nil {
log.Printf("QueryVertex NewPredictionClient - Err:%s", err)
}
defer c.Close()
.
.
I'm unfamiliar with Google's (Vertex?) AI Platform and unable to test this hypothesis but it appears that the API uses location-specific endpoints.
Can you try configuring the client's ClientOption to specify the specific regional endpoint, i.e.:
url := fmt.Sprintf("https://%s-aiplatform.googleapis.com", location)
opts := []option.ClientOption{
option.WithEndpoint(url),
}
And:
package main
import (
"context"
"fmt"
"log"
"os"
aiplatform "cloud.google.com/go/aiplatform/apiv1"
"google.golang.org/api/option"
aiplatformpb "google.golang.org/genproto/googleapis/cloud/aiplatform/v1"
"google.golang.org/protobuf/types/known/structpb"
)
const file = "MY_BASE64_IMAGE"
func main() {
// Values from the environment
project := os.Getenv("PROJECT")
location := os.Getenv("LOCATION")
endpoint := os.Getenv("ENDPOINT")
ctx := context.Background()
// Configure the client with a region-specific endpoint
url := fmt.Sprintf("https://%s-aiplatform.googleapis.com", location)
opts := []option.ClientOption{
option.WithEndpoint(url),
}
c, err := aiplatform.NewPredictionClient(ctx, opts...)
if err != nil {
log.Fatal(err)
}
defer c.Close()
parameters, err := structpb.NewValue(map[string]interface{}{
"confidenceThreshold": 0.2,
"maxPredictions": 5,
})
if err != nil {
log.Fatal(err)
}
instance, err := structpb.NewValue(map[string]interface{}{
"content": file,
})
if err != nil {
log.Printf("QueryVertex structpb.NewValue instance - Err:%s", err)
}
rqst := &aiplatformpb.PredictRequest{
Endpoint: fmt.Sprintf("projects/%s/locations/%s/endpoints/%s",
project,
location,
endpoint,
),
Instances: []*structpb.Value{
instance,
},
Parameters: parameters,
}
resp, err := c.Predict(ctx, rqst)
if err != nil {
log.Fatal(err)
}
log.Printf("QueryVertex Res:%+v", resp)
}
Try to do something like this
[...]
url := fmt.Sprintf("%s-aiplatform.googleapis.com:443", location)
[..]

Testing NATS-streaming in Kubernetes with minimal effort

I wanted to test a very basic application for NATS-streaming on Kubernetes. To do so, I followed the commands from the official NATS-docs.
It basically comes down to running
kubectl apply -f https://raw.githubusercontent.com/nats-io/k8s/master/nats-server/single-server-nats.yml
kubectl apply -f https://raw.githubusercontent.com/nats-io/k8s/master/nats-streaming-server/single-server-stan.yml
in a terminal with access to the cluster (it's a kind-cluster in my case).
I used stan.go as the NATS-streaming-client. Here is the code I tried to connect to the NATS-streaming-server:
package main
import stan "github.com/nats-io/stan.go"
func main() {
sc, err := stan.Connect("stan", "test-client")
if err != nil {
panic(err)
}
if err := sc.Publish("test-subject", []byte("This is a test-message!")); err != nil {
panic(err)
}
}
and this is the error I'm getting:
panic: nats: no servers available for connection
goroutine 1 [running]:
main.main()
/Users/thilt/tmp/main.go:9 +0x15d
exit status 2
so I think another name was used for the cluster or something. If I use the provided example with nats-box from the docs.nats-link above, it also doesn't work! Where did I go wrong here?
I will happily provide more information, if needed.
There is a great example in stan.go docs:
// Connect to NATS
nc, err := nats.Connect(URL, opts...)
if err != nil {
log.Fatal(err)
}
defer nc.Close()
sc, err := stan.Connect(clusterID, clientID, stan.NatsConn(nc))
if err != nil {
log.Fatalf("Can't connect: %v.\nMake sure a NATS Streaming Server is running at: %s", err, URL)
}
defer sc.Close()
Your error happens because by default stan connects to localhost address (source code):
// DefaultNatsURL is the default URL the client connects to
DefaultNatsURL = "nats://127.0.0.1:4222"
Notice that povided above example overwrite this default connection.
Stan source code is short and easy to analyze. I really recommend you to try to analyze it and figure out what it does.
Now let's put it all together; here is a working example:
package main
import (
nats "github.com/nats-io/nats.go"
stan "github.com/nats-io/stan.go"
)
func main() {
// Create a NATS connection
nc, err := nats.Connect("nats://nats:4222")
if err != nil {
panic(err)
}
// Then pass it to the stan.Connect() call.
sc, err := stan.Connect("stan", "me", stan.NatsConn(nc))
if err != nil {
panic(err)
}
if err := sc.Publish("test-subject", []byte("This is a test-message!")); err != nil {
panic(err)
}
}

List Openshift objects via Go client API

Trying to write a microservice to manage imagestreams on my Openshift cluster. I read the oc client code to work out how to read my kubeconfig and create the Client.
I can make requests with the Kubernetes Client to get the Kubernetes objects, e.g. pods, but any requests I make with the Openshift Client returns back an empty list.
I'm new to Go as well, so I'm sure I'm doing something wrong. Here's what I have so far:
package main
import (
"fmt"
"log"
"github.com/spf13/pflag"
kapi "k8s.io/kubernetes/pkg/api"
"github.com/openshift/origin/pkg/cmd/util/clientcmd"
)
func main() {
flags := pflag.FlagSet{}
factory := clientcmd.New(&flags)
osclient, kclient, err := factory.Clients()
if err != nil {
log.Fatalln("Error:", err)
}
config, _ := factory.ClientConfig()
fmt.Println("KClient config", config)
config, _ = factory.OpenShiftClientConfig.ClientConfig()
fmt.Println("OSClient config", config)
// Empty list!
projects, err := osclient.Projects().List(kapi.ListOptions{})
if err != nil {
log.Println("Error:", err)
} else {
fmt.Println("Projects", projects, len(projects.Items))
}
// Also empty list
buildconfigs, err := osclient.BuildConfigs("my-project").List(kapi.ListOptions{})
if err != nil {
log.Println("Error:", err)
} else {
fmt.Println("Buildconfigs", buildconfigs, len(buildconfigs.Items))
}
// Works!
pods, err := kclient.Pods("my-project").List(kapi.ListOptions{})
if err != nil {
log.Println("Error:", err)
} else {
fmt.Println("Pods", len(pods.Items))
for _, pod := range pods.Items {
fmt.Println(pod.ObjectMeta.Name)
}
}
// Permission error, as expected
namespaces, err := kclient.Namespaces().List(kapi.ListOptions{})
if err != nil {
log.Println("Error:", err)
} else {
fmt.Println("Namespaces", namespaces, len(namespaces.Items))
}
}
You were ever so close and the issue was a tiny one: you needed to include the following additional import:
import _ "github.com/openshift/origin/pkg/api/install"
I'm not fully clear what the import actually does, but evidently it causes necessary additional functionality to be linked into the binary, without which the OpenShift client doesn't work (returns empty lists).
All of the OpenShift command line tools include that import, and as of writing many include some/all of the following as well:
import (
_ "github.com/openshift/origin/pkg/api/install"
_ "k8s.io/kubernetes/pkg/api/install"
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
_ "k8s.io/kubernetes/pkg/apis/batch/install"
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
)
Finally, here's a full code example which works for me (updated against origin v3.6.0-alpha):
package main
import (
"fmt"
_ "github.com/openshift/origin/pkg/api/install"
"github.com/openshift/origin/pkg/cmd/util/clientcmd"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/apis/meta/v1"
)
func main() {
factory := clientcmd.New(pflag.CommandLine)
pflag.Parse()
oc, kc, err := factory.Clients()
if err != nil {
panic(err)
}
namespace, _, err := factory.DefaultNamespace()
if err != nil {
panic(err)
}
pods, err := kc.Core().Pods(namespace).List(v1.ListOptions{})
if err != nil {
panic(err)
}
for _, pod := range pods.Items {
fmt.Printf("Pod: %s\n", pod.Name)
}
buildconfigs, err := oc.BuildConfigs(namespace).List(v1.ListOptions{})
if err != nil {
panic(err)
}
for _, buildconfig := range buildconfigs.Items {
fmt.Printf("BuildConfig: %s\n", buildconfig.Name)
}
}
To run this example, you will currently need to vendor OpenShift and its dependencies. One very hacky way to do this is as follows:
rm -rf vendor
mkdir -p vendor/github.com/openshift/origin
ln -s $GOPATH/src/github.com/openshift/origin/vendor/* vendor
ln -s $GOPATH/src/github.com/openshift/origin/vendor/github.com/* vendor/github.com
ln -s $GOPATH/src/github.com/openshift/origin/vendor/github.com/openshift/* vendor/github.com/openshift
ln -s $GOPATH/src/github.com/openshift/origin/pkg vendor/github.com/openshift/origin
Finally, it is intended to make a proper standalone Go client for OpenShift - the backlog card for this is at https://trello.com/c/PTDrY0GF/794-13-client-provide-go-client-similar-to-kubernetes.

How to connect to client in GCE in GO

I can't able to connect to client. Is there any way to pass private key id and private key to client for get authorized?
So, far i see:
ctx := context.Background()
client, err := google.DefaultClient(ctx, compute.ComputeScope)
if err != nil {
//...
}
computeService, err := compute.New(client)
if err != nil {
//...
}
Firstly, Need to create a credential for service account in GCE and it will download a json file and it will use for authorize the client.
Sample Code :
data, err := ioutil.ReadFile("downloadedfile.json")
if err != nil {
log.Fatal(err)
}
conf, err := google.JWTConfigFromJSON(data, compute.ComputeScope) // give the specific permission for this client.
if err != nil {
log.Fatal(err)
}
client = conf.Client(oauth2.NoContext)
computeService, err := compute.New(client)
if err != nil {
//...
}

How can I create a simple client app with the Kubernetes Go library?

I'm struggling with the Kubernetes Go library. The docs--at least the ones I found--appear out-of-date with the library itself. The example provided does not build because of issues with the imports. I'm just trying to do something simple: get a Service object by name and print some attributes (like nodePort). I just need a simple example of library usage to get me going.
I could easily do this using the RESTful API but that feels like re-inventing the wheel.
So after a little experimentation and a hint from the k8s Slack channel, I have this example. Perhaps someone can update the example with a proper import path.
package main
import (
"fmt"
"log"
"github.com/kubernetes/kubernetes/pkg/api"
client "github.com/kubernetes/kubernetes/pkg/client/unversioned"
)
func main() {
config := client.Config{
Host: "http://my-kube-api-server.me:8080",
}
c, err := client.New(&config)
if err != nil {
log.Fatalln("Can't connect to Kubernetes API:", err)
}
s, err := c.Services(api.NamespaceDefault).Get("some-service-name")
if err != nil {
log.Fatalln("Can't get service:", err)
}
fmt.Println("Name:", s.Name)
for p, _ := range s.Spec.Ports {
fmt.Println("Port:", s.Spec.Ports[p].Port)
fmt.Println("NodePort:", s.Spec.Ports[p].NodePort)
}
}
Here's how to do it with the latest Go client.
If you're inside the k8s cluster:
package main
import (
"fmt"
"k8s.io/client-go/1.5/kubernetes"
"k8s.io/client-go/1.5/pkg/api/v1"
"k8s.io/client-go/1.5/rest"
)
func main() {
config, err = rest.InClusterConfig()
if err != nil {
return nil, err
}
c, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
// Get Pod by name
pod, err := c.Pods(v1.NamespaceDefault).Get("my-pod")
if err != nil {
fmt.Println(err)
return
}
// Print its creation time
fmt.Println(pod.GetCreationTimestamp())
}
And if you're outside of the cluster:
package main
import (
"fmt"
"k8s.io/client-go/1.5/kubernetes"
"k8s.io/client-go/1.5/pkg/api/v1"
"k8s.io/client-go/1.5/tools/clientcmd"
)
func main() {
config, err := clientcmd.BuildConfigFromFlags("", <kube-config-path>)
if err != nil {
return nil, err
}
c, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
// Get Pod by name
pod, err := c.Pods(v1.NamespaceDefault).Get("my-pod")
if err != nil {
fmt.Println(err)
return
}
// Print its creation time
fmt.Println(pod.GetCreationTimestamp())
}
I have gone into more detail on this in a blog post.
With kubernetes go client, it could be done this way:
package main
import (
"flag"
"fmt"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/tools/clientcmd"
)
var (
kubeconfig = flag.String("kubeconfig", "./config", "absolute path to the kubeconfig file")
)
func main() {
flag.Parse()
// uses the current context in kubeconfig
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
panic(err.Error())
}
// creates the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
services, err := clientset.Core().Services("").List(v1.ListOptions{})
if err != nil {
panic(err.Error())
}
fmt.Printf("There are %d pods in the cluster\n", len(services.Items))
for _, s := range services.Items {
for p, _ := range s.Spec.Ports {
fmt.Println("Port:", s.Spec.Ports[p].Port)
fmt.Println("NodePort:", s.Spec.Ports[p].NodePort)
}
}
}

Resources