github.com/zntrio/harp/v2@v2.0.9/pkg/tasks/bundle/diff.go (about)

     1  // Licensed to Elasticsearch B.V. under one or more contributor
     2  // license agreements. See the NOTICE file distributed with
     3  // this work for additional information regarding copyright
     4  // ownership. Elasticsearch B.V. licenses this file to you under
     5  // the Apache License, Version 2.0 (the "License"); you may
     6  // not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing,
    12  // software distributed under the License is distributed on an
    13  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14  // KIND, either express or implied.  See the License for the
    15  // specific language governing permissions and limitations
    16  // under the License.
    17  
    18  package bundle
    19  
    20  import (
    21  	"context"
    22  	"encoding/json"
    23  	"errors"
    24  	"fmt"
    25  
    26  	"github.com/zntrio/harp/v2/pkg/bundle"
    27  	"github.com/zntrio/harp/v2/pkg/bundle/compare"
    28  	"github.com/zntrio/harp/v2/pkg/sdk/convert"
    29  	"github.com/zntrio/harp/v2/pkg/sdk/types"
    30  	"github.com/zntrio/harp/v2/pkg/tasks"
    31  )
    32  
    33  // DiffTask implements secret container difference task.
    34  type DiffTask struct {
    35  	SourceReader      tasks.ReaderProvider
    36  	DestinationReader tasks.ReaderProvider
    37  	OutputWriter      tasks.WriterProvider
    38  	GeneratePatch     bool
    39  }
    40  
    41  // Run the task.
    42  func (t *DiffTask) Run(ctx context.Context) error {
    43  	// Check arguments
    44  	if types.IsNil(t.SourceReader) {
    45  		return errors.New("unable to run task with a nil sourceReader provider")
    46  	}
    47  	if types.IsNil(t.DestinationReader) {
    48  		return errors.New("unable to run task with a nil destinationReader provider")
    49  	}
    50  	if types.IsNil(t.OutputWriter) {
    51  		return errors.New("unable to run task with a nil outputWriter provider")
    52  	}
    53  
    54  	// Create input reader
    55  	readerSrc, err := t.SourceReader(ctx)
    56  	if err != nil {
    57  		return fmt.Errorf("unable to open source bundle: %w", err)
    58  	}
    59  
    60  	// Load source bundle
    61  	bSrc, err := bundle.FromContainerReader(readerSrc)
    62  	if err != nil {
    63  		return fmt.Errorf("unable to load source bundle content: %w", err)
    64  	}
    65  
    66  	// Create input reader
    67  	readerDst, err := t.DestinationReader(ctx)
    68  	if err != nil {
    69  		return fmt.Errorf("unable to open destination bundle: %w", err)
    70  	}
    71  
    72  	// Load destination bundle
    73  	bDst, err := bundle.FromContainerReader(readerDst)
    74  	if err != nil {
    75  		return fmt.Errorf("unable to load destination bundle content: %w", err)
    76  	}
    77  
    78  	// Calculate diff
    79  	report, err := compare.Diff(bSrc, bDst)
    80  	if err != nil {
    81  		return fmt.Errorf("unable to calculate bundle difference: %w", err)
    82  	}
    83  
    84  	// Create output writer
    85  	writer, err := t.OutputWriter(ctx)
    86  	if err != nil {
    87  		return fmt.Errorf("unable to open output writer: %w", err)
    88  	}
    89  
    90  	if !t.GeneratePatch {
    91  		// Encode as JSON
    92  		if err := json.NewEncoder(writer).Encode(report); err != nil {
    93  			return fmt.Errorf("unable to marshal JSON OpLog: %w", err)
    94  		}
    95  	} else {
    96  		// Convert optlog as a patch
    97  		patch, err := compare.ToPatch(report)
    98  		if err != nil {
    99  			return fmt.Errorf("unable to convert oplog as a bundle patch: %w", err)
   100  		}
   101  
   102  		// Marshal as YAML
   103  		out, err := convert.PBtoYAML(patch)
   104  		if err != nil {
   105  			return fmt.Errorf("unable to marshal patch as YAML: %w", err)
   106  		}
   107  
   108  		// Write output
   109  		fmt.Fprintln(writer, string(out))
   110  	}
   111  
   112  	// No error
   113  	return nil
   114  }