Why argo-workflow report is not called when workflow step has outputs? - argo-workflows

Just wondering, why with argo-workflow, as seen here:
https://github.com/argoproj/argo-workflows/blob/master/workflow/executor/executor.go#L783
func (we *WorkflowExecutor) reportResult(ctx context.Context, result wfv1.NodeResult) error {
if !result.Outputs.HasOutputs() && !result.Progress.IsValid() {
return nil
}
...
err := we.upsertTaskResult(ctx, result)
Why when there is output, the upsertTaskResult is not called?
(took me a while to debug "k8s API denied" error because a wrong serviceAccount, the dirty solution found by developers was to no more use "output" ....)

Related

How to trigger a rollout restart on deployment resource from controller-runtime

I have been using kubebuilder for writing custom controller, and aware of Get(), Update(), Delete() methods that it provides. But Now I am looking for a method which mimic the behaviour of kubectl rollout restart deployment. If there is no such direct method then I am looking for correct way to mimic the same.
type CustomReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
}
func (r *CustomReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
configMap := &v1.ConfigMap{}
err = r.Get(ctx, req.namespacedName, configMap)
if err != nil {
logger.Error(err, "Failed to GET configMap")
return ctrl.Result{}, err
}
Say in above code I read a deployment name from the configmap and rollout restart the same as follows:
val := configMap.Data["config.yml"]
config := Config{}
if err := yaml.Unmarshal([]byte(val), &config); err != nil {
logger.Error(err, "failed to unmarshal config data")
return ctrl.Result{}, err
}
// Need equivalent of following
// r.RolloutRestart(config.DeploymentName)
In all cases where you wish to replicate kubectl behavior, the answer is always to increase its verbosity and it'll show you exactly -- sometimes down to the wire payloads -- what it is doing.
For rollout restart, one will find that it just bumps an annotation on the Deployment/StatefulSet/whatever and that causes the outer object to be "different," and triggering a reconciliation run
You can squat on their annotation, or you can make up your own, or you can use a label change -- practically any "meaningless" change will do

cadence go-client/ client to reach server for fetching workflow results in panic

First time user of Cadence:
Scenario
I have a cadence server running in my sandbox environment.
Intent is to fetch the workflow status
I am trying to use this cadence client
go.uber.org/cadence/client
on my local host to talk to my sandbox cadence server.
This is my simple code snippet:
var cadClient client.Client
func main() {
wfID := "01ERMTDZHBYCH4GECHB3J692PC" << I got this from cadence-ui
ctx := context.Background()
wf := cadClientlient.GetWorkflow(ctx, wfID,"") <<< Panic hits here
log.Println("Workflow RunID: ",wf.GetID())
}
I am sure getting it wrong because the client does not know how to reach the cadence server.
I referred this https://cadenceworkflow.io/docs/go-client/ to find the correct usage but could not find any reference (possible that I might have missed it).
Any help in how to resolve/implement this, will be of much help
I am not sure what panic you got. Based on the code snippet, it's likely that you haven't initialized the client.
To initialize it, follow the sample code here: https://github.com/uber-common/cadence-samples/blob/master/cmd/samples/common/sample_helper.go#L82
and
https://github.com/uber-common/cadence-samples/blob/aac75c7ca03ec0c184d0f668c8cd0ea13d3a7aa4/cmd/samples/common/factory.go#L113
ch, err := tchannel.NewChannelTransport(
tchannel.ServiceName(_cadenceClientName))
if err != nil {
b.Logger.Fatal("Failed to create transport channel", zap.Error(err))
}
b.Logger.Debug("Creating RPC dispatcher outbound",
zap.String("ServiceName", _cadenceFrontendService),
zap.String("HostPort", b.hostPort))
b.dispatcher = yarpc.NewDispatcher(yarpc.Config{
Name: _cadenceClientName,
Outbounds: yarpc.Outbounds{
_cadenceFrontendService: {Unary: ch.NewSingleOutbound(b.hostPort)},
},
})
if b.dispatcher != nil {
if err := b.dispatcher.Start(); err != nil {
b.Logger.Fatal("Failed to create outbound transport channel: %v", zap.Error(err))
client := workflowserviceclient.New(b.dispatcher.ClientConfig(_cadenceFrontendService))

"Powershell Module Unavailable" error trying to connect to minikube

This is the error am getting, please help me anyone.
Error starting host: Error creating host: Error executing step: Running pre
create checks.
: Hyper-V PowerShell Module is not available
I confirm issue.
Looking at code:
powershell.go in recent minikube
func hypervAvailable() error {
stdout, err := cmdOut("#(Get-Command hyper-v\\Get-VM).ModuleName")
if err != nil {
return err
}
resp := parseLines(stdout)
if resp[0] != "Hyper-V" {
return ErrNotInstalled
}
return nil
}
and simple check on my box gives
C:\Users\slavko> (Get-Command hyper-v\Get-VM).ModuleName
hyper-v
So that check is quite silly, as that check in Go is case sensitive.
UPD: Code above is fixed 10 hrs ago. Check 0.25.2

TDD with database and Go

I'm trying to wrap my head around test driven development with Go and having an issue testing my CRUD functions since they are written for my production database. I'm coming from Ruby on Rails so I am used to using a test database, but Go doesn't seem to be too friendly in this regard.
So, how does one go about testing CRUD with Go?
main.go
package main
import (
"database/sql"
)
type book struct {
id int `json:"id"`
isbn string `json:"isbn"`
title string `json:"title"`
author string `json:"author"`
price float32 `json:"price"`
}
// type Books []*Book
// CRUD functions for Book
func (b *book) getBook(db *sql.DB) error {
return db.QueryRow("SELECT * FROM books WHERE id=$1", b.id).Scan(&b)
}
app.go
func (a *App) Initialize(dbname string) {
var err error
a.DB, err = sql.Open("postgres", "postgresql://localhost:5432/bookstore?sslmode=disable")
if err != nil {
log.Fatal(err)
}
}
my test
func TestGetBook(t *testing.T) {
clearTable()
addBook(1)
req, _ := http.NewRequest("GET", "/book/1", nil)
response := executeRequest(req)
checkResponseCode(t, http.StatusOK, response.Code)
}
The problem is that this keeps on looking at the books table in my DB, not the books_test table I'd like to use for testing. How can I go about making ONLY the tests use the books_test DB?
You should create a dev/test database which should be a complete copy of your production database. You will never want to run test directly against your production database since too many unexpected issues could happen.
A workaround would be starting up your app first, which creates the connection to your database, then run the test. You can use IntelliJ to achieve this.
TDD in my opinion is great for developing business logic layer code since new models and business processes can have unexpected impacts on existing ones.
#Godzilla74, there'are 2 solutions: enable SSL for test DB (try to check database settings or ask your system administrator) of have completely different setting for test:
func (a *App) Initialize(dbname string) {
var err error
pgsettings := os.Getenv("PGSETTINGS")
if pgsettins == "" {
// default options if not overridden
pgsettins := "postgresql://localhost:5432/bookstore?sslmode=disable"
}
a.DB, err = sql.Open("postgres", pgsettins)
if err != nil {
log.Fatal(err)
}
}
So you can run set environment setting to any required value and run app, like so:
export PGSETTINGS="postgresql://localhost:5432/bookstore_test?sslmode=disable"
go run main.go

Get error code number from postgres in Go

I'm simply unable to retrieve the error code number when I get an error in postgres.
In the test of my program I know I'll get the following error
" pq: duplicate key value violates unique constraint "associations_pkey"".
Looking in the postgres docs this is most likely an pq error code of 23505.
I need to get that number in my Go program so that I can check on different types of errors and respond to the end user in a helpful way.
However, I can't seem to get hold of the error code in Go, only the error message. My code is as follows:
stmt, _ := DB.Prepare("INSERT INTO table (column_1) VALUES ($1)")
_, err = stmt.Exec("12324354")
if err != nil {
log.Println("Failed to stmt .Exec while trying to insert new association")
log.Println(err.Error())
fmt.Println(err.Code())
} else {
Render.JSON(w, 200, "New row was created succesfully")
}
You need to type assert the error to the type *pq.Error:
pqErr := err.(*pq.Error)
log.Println(pqErr.Code)
This is written in the documentation. As you see you can extract it in this way:
if err, ok := err.(*pq.Error); ok {
fmt.Println(err.Code)
}
Do not forget to remove the underscore from your import _ "github.com/lib/pq". As you see err has a lot of information about the error (not only Code but many others).
Notice that you can't compare it directly to some code (it is of ErrorCode type).
So you have to convert it to string and compare against a string.
https://godoc.org/github.com/lib/pq#Error