mortar icon indicating copy to clipboard operation
mortar copied to clipboard

Unable to add/remove Secret stringData

Open oeuftete opened this issue 5 years ago • 6 comments

This may just be a longer way of asking for #92.

Using mortar 0.3.3, starting with a simple deployment with a Secret:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: patchtest
  namespace: default
  labels:
    app: patchtest
spec:
  selector:
    matchLabels:
      app: patchtest
  replicas: 1
  template:
    metadata:
      labels:
        app: patchtest
    spec:
      containers:
      - name: foo
        image: busybox
        command:
        - cat
        tty: true
---
apiVersion: v1
kind: Secret
metadata:
  name: patchtest
  namespace: default
type: Opaque
stringData:
  foo: foo

mortar fire . patchtest works. Now add another entry to the stringData map:

stringData:
  foo: foo
  bar: bar
/__enclose_io_memfs__/lib/ruby/gems/2.4.0/gems/k8s-client-0.8.3/lib/k8s/transport.rb:219:in `parse_response': PATCH /api/v1/namespaces/default/secrets/patchtest => HTTP 500 Internal Server Error: jsonpatch add operation does not apply: doc is missing path: /stringData/bar (K8s::Error::InternalError)
	from /__enclose_io_memfs__/lib/ruby/gems/2.4.0/gems/k8s-client-0.8.3/lib/k8s/transport.rb:242:in `request'
	from /__enclose_io_memfs__/lib/ruby/gems/2.4.0/gems/k8s-client-0.8.3/lib/k8s/resource_client.rb:293:in `json_patch'
	from /__enclose_io_memfs__/lib/ruby/gems/2.4.0/gems/k8s-client-0.8.3/lib/k8s/client.rb:263:in `patch_resource'
	from /__enclose_io_memfs__/lib/ruby/gems/2.4.0/gems/k8s-client-0.8.3/lib/k8s/stack.rb:108:in `block in apply'
	from /__enclose_io_memfs__/lib/ruby/gems/2.4.0/gems/k8s-client-0.8.3/lib/k8s/stack.rb:100:in `map'
	from /__enclose_io_memfs__/lib/ruby/gems/2.4.0/gems/k8s-client-0.8.3/lib/k8s/stack.rb:100:in `apply'
	from /__enclose_io_memfs__/lib/ruby/gems/2.4.0/gems/kontena-mortar-0.3.3/lib/mortar/fire_command.rb:64:in `execute'
	from /__enclose_io_memfs__/lib/ruby/gems/2.4.0/gems/clamp-1.3.0/lib/clamp/command.rb:66:in `run'
	from /__enclose_io_memfs__/lib/ruby/gems/2.4.0/gems/clamp-1.3.0/lib/clamp/subcommand/execution.rb:18:in `execute'
	from /__enclose_io_memfs__/lib/ruby/gems/2.4.0/gems/clamp-1.3.0/lib/clamp/command.rb:66:in `run'
	from /__enclose_io_memfs__/lib/ruby/gems/2.4.0/gems/clamp-1.3.0/lib/clamp/command.rb:140:in `run'
	from /__enclose_io_memfs__/lib/ruby/gems/2.4.0/gems/kontena-mortar-0.3.3/bin/mortar:13:in `<top (required)>'
	from /__enclose_io_memfs__/lib/ruby/gems/2.4.0/bin/mortar:23:in `load'
	from /__enclose_io_memfs__/lib/ruby/gems/2.4.0/bin/mortar:23:in `<main>'

Removing a secret that does exist fails similarly:

/__enclose_io_memfs__/lib/ruby/gems/2.4.0/gems/k8s-client-0.8.3/lib/k8s/transport.rb:219:in `parse_response': PATCH /api/v1/namespaces/default/secrets/patchtest => HTTP 500 Internal Server Error: jsonpatch remove operation does not apply: doc is missing path: /stringData/foo (K8s::Error::InternalError)

The workaround is to do something like mortar fire --output . patchtest | kubectl apply -f -, which I think will work fine when no new objects have been added... if there are new ones, they won't get the annotations for the shot, though. To ensure the annotations are in place, run mortar fire . patchtest immediately afterward.

oeuftete avatar Apr 25 '19 14:04 oeuftete

The workaround is to do something like mortar fire --output . patchtest | kubectl apply -f -, which I think will work fine when no new objects have been added... if there are new ones, they won't get the annotations for the shot, though. To ensure the annotations are in place, run mortar fire . patchtest immediately afterward.

It might be nice if the output from mortar fire --output could optionally include its annotations and labels so that the pipe to kubectl could be one step.

oeuftete avatar Apr 25 '19 14:04 oeuftete

Hmm, interesting. Looking from the kube API side secrets are actually patchable:

$ kubectl api-resources --verbs patch | grep secrets
secrets                                                                       true         Secret

The problem is that

stringData:
  foo: foo

is never stored on the API as such. What gets stored is only the binary (base64 encoded) data key.

jnummelin avatar May 15 '19 14:05 jnummelin

As a workaround I think you should be able to get this to work if you first fire with

data:
  foo: Zm9vCg== # foo in base64

and then later on fire again with

data:
  foo: Zm9vCg== # foo in base64
  bar: YmFyCg== # bar in base64

jnummelin avatar May 15 '19 14:05 jnummelin

Confirmed to work as expected:

apiVersion: v1
kind: Secret
metadata:
  name:  test-secret
  namespace: default
data:
   foo: Zm9vCg==
type: Opaque
$ mortar fire secrets-test/ secrets
shot 'secrets' successfully!

Add another secret key:

apiVersion: v1
kind: Secret
metadata:
  name:  test-secret
  namespace: default
data:
   foo: Zm9vCg==
   bar: YmFyCg==
type: Opaque
$ mortar fire secrets-test/ secrets
shot 'secrets' successfully!

$ kubectl describe secrets test-secret
Name:         test-secret
Namespace:    default
Labels:       mortar.kontena.io/shot=secrets
Annotations:  mortar.kontena.io/shot-checksum: db2ef5015bfb04228749e5a42bee2495

Type:  Opaque

Data
====
bar:  4 bytes
foo:  4 bytes

jnummelin avatar May 15 '19 15:05 jnummelin

Thanks, I can definitely work with encoding the secrets before having them consumed by mortar and using data. Though the full stringData support would be nice to have.

oeuftete avatar May 15 '19 15:05 oeuftete

Though the full stringData support would be nice to have.

That would mean that Mortar, actually the underlying k8s-client gem, would need to understand the specifics of given resource kind. I.e. have typed resources.

Currently much of the power, generic mortar shots (a.k.a. k8s-client stacks), easy way to work with CRDs etc. are possible as the resources are not typed at all on the client side. Unless we find a nice way to be able to work with either typed or untyped resources.

Having typed resources on the client side just makes the maintenance bit painfull as kube api evolves super fast :)

jnummelin avatar Jun 03 '19 09:06 jnummelin