Skip to content
This repository was archived by the owner on Aug 12, 2025. It is now read-only.

Commit ba7a177

Browse files
committed
Add support for local caching of CA cert/key to ease development
1 parent da79951 commit ba7a177

File tree

5 files changed

+115
-11
lines changed

5 files changed

+115
-11
lines changed

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,24 @@ make manifests
199199

200200
As always with `make`, you can force the rebuilding of a component with `make -B <target>`.
201201

202+
## Running locally
203+
204+
You can run the `manager` locally on your own laptop in order to ease and speed development, or even run it through a debugger. The steps are:
205+
206+
1. Create a kubernetes bootstrap cluster, e.g. kind
207+
1. Set your `KUBECONFIG` to point to that cluster, e.g. `export KUBECONFIG=...`
208+
1. Create a local OS/arch `manager` binary, essentially `make manager`. This will save it as `bin/manager-<os>-<arch>`, e.g. `bin/manager-linux-arm64` or `bin/manager-darwin-amd64`
209+
1. Generate your yaml `./generate-yaml.sh`
210+
1. Run the manager against the cluster with the local configs, `bin/manager-darwin-amd64 -config ./config/default/machine_configs.yaml -ca-cache ./out/cache.json`
211+
212+
In the above example:
213+
214+
* We are running on macOS (`darwin`) and an Intel x86_64 (`amd64`)
215+
* We are using the default config file `./config/default/machine_configs.yaml`
216+
* We are caching the CA keys and certs in `out/cache.json`
217+
218+
Caching the CA caches the certs **and the keys**. Only do this in test mode, or if you really are sure what you are doing. The purpose, in this case, is to allow you to stop and start the process, and pick up existing certs.
219+
202220
## References
203221

204222
* [kubeadm yaml api](https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2)

cmd/clusterctl/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,12 @@ func main() {
3838
}
3939

4040
// get a deployer, which is needed at various stages
41-
deployer := deployer.New(deployer.Params{
41+
deployer, err := deployer.New(deployer.Params{
4242
Client: client,
4343
})
44+
if err != nil {
45+
klog.Fatalf("unable to get deployer: %v", err)
46+
}
4447

4548
common.RegisterClusterProvisioner("packet", deployer)
4649
cmd.Execute()

cmd/manager/main.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ func main() {
5353
metricsAddr := flag.String("metrics-addr", ":8080", "The address the metric endpoint binds to.")
5454

5555
machineSetupConfig := flag.String("config", "/etc/machineconfig/machine_configs.yaml", "path to the machine setup config")
56+
caCache := flag.String("ca-cache", "", "path to file to save cluster credentials; should be used for development purposes only, as it saves actual CA credentials")
5657
flag.Parse()
5758

5859
log := logf.Log.WithName("packet-controller-manager")
@@ -77,10 +78,14 @@ func main() {
7778
klog.Fatalf("unable to get Packet client: %v", err)
7879
}
7980
// get a deployer, which is needed at various stages
80-
deployer := deployer.New(deployer.Params{
81-
Client: client,
82-
Port: controlPort,
81+
deployer, err := deployer.New(deployer.Params{
82+
Client: client,
83+
Port: controlPort,
84+
CACache: *caCache,
8385
})
86+
if err != nil {
87+
klog.Fatalf(err.Error())
88+
}
8489

8590
clusterActuator, err := cluster.NewActuator(cluster.ActuatorParams{
8691
ClustersGetter: cs.ClusterV1alpha1(),

pkg/cloud/packet/actuators/cluster/actuator.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,15 @@ func NewActuator(params ActuatorParams) (*Actuator, error) {
5353
func (a *Actuator) Reconcile(cluster *clusterv1.Cluster) error {
5454
log.Printf("Reconciling cluster %v.", cluster.Name)
5555
// ensure that we have a CA cert/key and save it
56-
if _, ok := a.deployer.Certs[cluster.Name]; !ok {
56+
if cert, _ := a.deployer.GetCA(cluster.Name); cert == nil {
5757
caCertAndKey, err := ca.GenerateCACertAndKey(cluster.Name, "")
5858
if err != nil {
5959
return fmt.Errorf("unable to generate CA cert and key: %v", err)
6060
}
61-
a.deployer.Certs[cluster.Name] = caCertAndKey
61+
err = a.deployer.PutCA(cluster.Name, caCertAndKey)
62+
if err != nil {
63+
return fmt.Errorf("unable to save CA cert and key: %v", err)
64+
}
6265
}
6366
return nil
6467
}
@@ -67,6 +70,6 @@ func (a *Actuator) Reconcile(cluster *clusterv1.Cluster) error {
6770
func (a *Actuator) Delete(cluster *clusterv1.Cluster) error {
6871
log.Printf("Deleting cluster %v.", cluster.Name)
6972
// remove the CA cert key
70-
delete(a.deployer.Certs, cluster.Name)
73+
a.deployer.DeleteCA(cluster.Name)
7174
return nil
7275
}

pkg/cloud/packet/deployer/deploy.go

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ package deployer
1818

1919
import (
2020
"crypto/x509"
21+
"encoding/json"
2122
"encoding/pem"
2223
"fmt"
2324
"log"
25+
"os"
2426
"time"
2527

2628
"github.com/packethost/cluster-api-provider-packet/pkg/cloud/packet"
@@ -43,24 +45,33 @@ const (
4345
// Deployer satisfies the ProviderDeployer(https://github.com/kubernetes-sigs/cluster-api/blob/master/cmd/clusterctl/clusterdeployer/clusterdeployer.go) interface.
4446
type Deployer struct {
4547
client *packet.PacketClient
48+
caCache string
4649
ControlPort int
4750
// Certs map of clusterName to CA CertificateAuthority pointers. Each CertificateAuthority contains the Certificate and PrivateKey as its PEM-Encoded bytes
4851
Certs map[string]*cert.CertificateAuthority
4952
}
5053

5154
// Params is used to create a new deployer.
5255
type Params struct {
53-
Client *packet.PacketClient
54-
Port int
56+
Client *packet.PacketClient
57+
Port int
58+
CACache string
5559
}
5660

5761
// New returns a new Deployer.
58-
func New(params Params) *Deployer {
59-
return &Deployer{
62+
func New(params Params) (*Deployer, error) {
63+
d := Deployer{
6064
client: params.Client,
65+
caCache: params.CACache,
6166
ControlPort: params.Port,
6267
Certs: map[string]*cert.CertificateAuthority{},
6368
}
69+
// start by loading cache, if needed
70+
err := d.readCache()
71+
if err != nil {
72+
return nil, fmt.Errorf("unable to read CA cache %s: %v", d.caCache, err)
73+
}
74+
return &d, nil
6475
}
6576

6677
// GetIP returns IP address of the machine in the cluster. If no machine is given, find the IP for the cluster itself, i.e. the master
@@ -234,3 +245,67 @@ func (d *Deployer) NewBootstrapToken(cluster *clusterv1.Cluster) (string, error)
234245
}
235246
return token, nil
236247
}
248+
249+
// readCache read the CAs that have been cached to a file
250+
// if blank, returns nil
251+
func (d *Deployer) readCache() error {
252+
if d.caCache == "" {
253+
return nil
254+
}
255+
// open for reading if it is there
256+
f, err := os.Open(d.caCache)
257+
switch {
258+
case err != nil && os.IsNotExist(err):
259+
return nil
260+
case err != nil:
261+
return fmt.Errorf("failed to open cache %s for reading: %v", d.caCache, err)
262+
}
263+
defer f.Close()
264+
// it exists, so read it
265+
decoder := json.NewDecoder(f)
266+
certs := map[string]*cert.CertificateAuthority{}
267+
if err := decoder.Decode(&certs); err != nil {
268+
return fmt.Errorf("error reading cache file %s: %v", d.caCache, err)
269+
}
270+
// save the data
271+
d.Certs = certs
272+
return nil
273+
}
274+
275+
// writeCache write the CAs to a cache file
276+
// if blank, returns nil
277+
func (d *Deployer) writeCache() error {
278+
if d.caCache == "" {
279+
return nil
280+
}
281+
// create the file if it does not exist
282+
f, err := os.OpenFile(d.caCache, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
283+
if err != nil {
284+
return fmt.Errorf("failed to open cache %s for writing: %v", d.caCache, err)
285+
}
286+
defer f.Close()
287+
encoder := json.NewEncoder(f)
288+
encoder.Encode(d.Certs)
289+
return nil
290+
}
291+
292+
// GetCA get the CA cert pair for a cluster
293+
func (d *Deployer) GetCA(name string) (*cert.CertificateAuthority, error) {
294+
c, ok := d.Certs[name]
295+
if !ok {
296+
return nil, nil
297+
}
298+
return c, nil
299+
}
300+
301+
// PutCA put the CA cert pair for a cluster
302+
func (d *Deployer) PutCA(name string, ca *cert.CertificateAuthority) error {
303+
d.Certs[name] = ca
304+
return d.writeCache()
305+
}
306+
307+
// DeleteCA remove the CA cert pair for a cluster
308+
func (d *Deployer) DeleteCA(name string) error {
309+
delete(d.Certs, name)
310+
return d.writeCache()
311+
}

0 commit comments

Comments
 (0)