Thanks to [k8s.io/code-generator](https://github.com/kubernetes/code-generator), Copy has now been replaced by a type-safe DeepCopy method living on each object, allowing you to simplify code significantly both in terms of volume and API error surface:
newNode := node.DeepCopy()
No error handling is necessary: this call never fails. If and only if the node is nil does DeepCopy() return nil.
To copy runtime.Objects there is an additional DeepCopyObject() method in the runtime.Object interface.
With the old method gone for good, clients need to update their copy invocations accordingly.
## Code generation and CustomResources
Using client-go’s dynamic client to access CustomResources is discouraged and superseded by type-safe code using the generators in [k8s.io/code-generator](https://github.com/kubernetes/code-generator). Check out the [Deep Dive on the Open Shift blog](https://blog.openshift.com/kubernetes-deep-dive-code-generation-customresources/) to learn about using code generation with client-go.
### Comment Blocks
You can now place tags in the comment block just above a type or function, or in the second block above. There is no distinction anymore between these two comment blocks. This used to a be a source of [subtle errors when using the generators](https://github.com/kubernetes/kubernetes/issues/53893):
```
// second block above
// +k8s:some-tag
// first block above
// +k8s:another-tag
type Foo struct {}
```
### Custom Client Methods
You can now use extended tag definitions to create custom verbs . This lets you expand beyond the verbs defined by HTTP. This opens the door to higher levels of customization.
For example, this block leads to the generation of the method UpdateScale(s \*autoscaling.Scale) (\*autoscaling.Scale, error):
```
// genclient:method=UpdateScale,verb=update,subresource=scale,input=k8s.io/kubernetes/pkg/apis/autoscaling.Scale,result=k8s.io/kubernetes/pkg/apis/autoscaling.Scale
```
### Resolving Golang Naming Conflicts
In more complex API groups it’s possible for Kinds, the group name, the Go package name, and the Go group alias name to conflict. This was not handled correctly prior to 1.9. The following tags resolve naming conflicts and make the generated code prettier:
```
// +groupName=example2.example.com
// +groupGoName=SecondExample
```
These are usually [in the doc.go file of an API package](https://github.com/kubernetes/code-generator/blob/release-1.9/_examples/crd/apis/example2/v1/doc.go#L18). The first is used as the CustomResource group name when RESTfully speaking to the API server using HTTP. The second is used in the generated Golang code (for example, in the clientset) to access the group version:
clientset.SecondExampleV1()
It’s finally possible to have dots in Go package names. In this section’s example, you would put the groupName snippet into the pkg/apis/example2.example.com directory of your project.
## Example projects
Kubernetes 1.9 includes a number of example projects which can serve as a blueprint for your own projects:
- [k8s.io/sample-apiserver](https://github.com/kubernetes/sample-apiserver) is a simple user-provided API server that is integrated into a cluster via [API aggregation](/docs/concepts/api-extension/apiserver-aggregation/).
- [k8s.io/sample-controller](https://github.com/kubernetes/sample-controller) is a full-featured [controller](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-api-machinery/controllers.md) (also called an operator) with shared informers and a workqueue to process created, changed or deleted objects. It is based on CustomResourceDefinitions and uses [k8s.io/code-generator](https://github.com/kubernetes/code-generator) to generate deepcopy functions, typed clientsets, informers, and listers.
## Vendoring
In order to update from the previous version 5 to version 6 of client-go, the library itself as well as certain third-party dependencies must be updated. Previously, this process had been tedious due to the fact that a lot of code got refactored or relocated within the existing package layout across releases. Fortunately, far less code had to move in the latest version, which should ease the upgrade procedure for most users.