blob: ece09348f81d9f686394487610891dc30150a926 [file] [log] [blame]
//go:build gofuzz
// +build gofuzz
// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package controller
import (
"context"
)
import (
fuzz "github.com/AdaLogics/go-fuzz-headers"
coreV1 "k8s.io/api/core/v1"
discovery "k8s.io/api/discovery/v1"
"k8s.io/apimachinery/pkg/api/errors"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
import (
"github.com/apache/dubbo-go-pixiu/pkg/network"
)
func InternalFuzzKubeController(data []byte) int {
networkID := network.ID("fakeNetwork")
fco := FakeControllerOptions{}
f := fuzz.NewConsumer(data)
f.AllowUnexportedFields()
err := f.GenerateStruct(&fco)
if err != nil {
return 0
}
controller, fx := NewFakeControllerWithOptions(fco)
controller.network = networkID
defer controller.Stop()
p, err := generatePodFuzz(f)
if err != nil {
return 0
}
err = addPodsForFuzzing(controller, fx, p)
if err != nil {
return 0
}
err = createServiceForFuzzing(controller, f)
if err != nil {
return 0
}
err = createEndpointsForFuzzing(f, controller)
if err != nil {
return 0
}
node, err := generateNodeForFuzzing(f)
if err != nil {
return 0
}
err = addNodesForFuzzing(controller, node)
if err != nil {
return 0
}
return 1
}
func generatePodFuzz(f *fuzz.ConsumeFuzzer) (*coreV1.Pod, error) {
pod := &coreV1.Pod{}
return pod, f.GenerateStruct(pod)
}
func generateNodeForFuzzing(f *fuzz.ConsumeFuzzer) (*coreV1.Node, error) {
node := &coreV1.Node{}
return node, f.GenerateStruct(node)
}
func addPodsForFuzzing(controller *FakeController, fx *FakeXdsUpdater, pods ...*coreV1.Pod) error {
for _, pod := range pods {
p, _ := controller.client.CoreV1().Pods(pod.Namespace).Get(context.Background(), pod.Name, metaV1.GetOptions{})
var newPod *coreV1.Pod
var err error
if p == nil {
newPod, err = controller.client.CoreV1().Pods(pod.Namespace).Create(context.Background(), pod, metaV1.CreateOptions{})
if err != nil {
return err
}
} else {
newPod, err = controller.client.CoreV1().Pods(pod.Namespace).Update(context.Background(), pod, metaV1.UpdateOptions{})
if err != nil {
return err
}
}
setPodReadyForFuzzing(newPod)
newPod.Status.PodIP = pod.Status.PodIP
newPod.Status.Phase = coreV1.PodRunning
_, _ = controller.client.CoreV1().Pods(pod.Namespace).UpdateStatus(context.Background(), newPod, metaV1.UpdateOptions{})
fx.Wait("proxy")
}
return nil
}
func setPodReadyForFuzzing(pod *coreV1.Pod) {
pod.Status.Conditions = []coreV1.PodCondition{
{
Type: coreV1.PodReady,
Status: coreV1.ConditionTrue,
LastTransitionTime: metaV1.Now(),
},
}
}
func addNodesForFuzzing(controller *FakeController, nodes ...*coreV1.Node) error {
fakeClient := controller.client
for _, node := range nodes {
_, err := fakeClient.CoreV1().Nodes().Create(context.Background(), node, metaV1.CreateOptions{})
if errors.IsAlreadyExists(err) {
if _, err := fakeClient.CoreV1().Nodes().Update(context.Background(), node, metaV1.UpdateOptions{}); err != nil {
return nil
}
} else if err != nil {
return err
}
}
return nil
}
func createServiceForFuzzing(controller *FakeController, f *fuzz.ConsumeFuzzer) error {
service := &coreV1.Service{}
namespace, err := f.GetString()
if err != nil {
return err
}
err = f.GenerateStruct(service)
if err != nil {
return err
}
_, err = controller.client.CoreV1().Services(namespace).Create(context.Background(), service, metaV1.CreateOptions{})
if err != nil {
return err
}
return nil
}
func createEndpointsForFuzzing(f *fuzz.ConsumeFuzzer, controller *FakeController) error {
labels := make(map[string]string)
// Add the reference to the service. Used by EndpointSlice logic only.
name, err := f.GetString()
if err != nil {
return err
}
labels[discovery.LabelServiceName] = name
eas := make([]coreV1.EndpointAddress, 0)
number, err := f.GetInt()
if err != nil {
return err
}
for i := 0; i < number%50; i++ {
ea := coreV1.EndpointAddress{}
err = f.GenerateStruct(&ea)
if err != nil {
return err
}
eas = append(eas, ea)
}
eps := make([]coreV1.EndpointPort, 0)
number, err = f.GetInt()
if err != nil {
return err
}
for i := 0; i < number%50; i++ {
ep := coreV1.EndpointPort{}
err = f.GenerateStruct(&ep)
if err != nil {
return err
}
eps = append(eps, ep)
}
endpoint := &coreV1.Endpoints{}
err = f.GenerateStruct(endpoint)
if err != nil {
return err
}
namespace, err := f.GetString()
if err != nil {
return err
}
if _, err := controller.client.CoreV1().Endpoints(namespace).Create(context.Background(), endpoint, metaV1.CreateOptions{}); err != nil {
if errors.IsAlreadyExists(err) {
_, err = controller.client.CoreV1().Endpoints(namespace).Update(context.Background(), endpoint, metaV1.UpdateOptions{})
}
if err != nil {
return err
}
}
endpointSlice := &discovery.EndpointSlice{}
err = f.GenerateStruct(endpointSlice)
if err != nil {
return err
}
if _, err := controller.client.DiscoveryV1().EndpointSlices(namespace).Create(context.Background(), endpointSlice, metaV1.CreateOptions{}); err != nil {
if errors.IsAlreadyExists(err) {
_, err = controller.client.DiscoveryV1().EndpointSlices(namespace).Update(context.Background(), endpointSlice, metaV1.UpdateOptions{})
}
if err != nil {
return err
}
}
return nil
}