Monday, January 3, 2022

Kubernetes ImagePullBackOff error

Recently I faced an issue while working Kubernetes cluster. I was trying to build docker image from local repository to test some changes in production before we merge the code. After building the docker image and recreating the container it was showing ImagePullBackOff error when I check the status with 

kubectl get pods

In this blog I am going to mention the possible cause for this error and will explain the resolution which worked for me.

In a Kubernetes, there’s an agent on for node which is called kubelet. This is responsible for running containers in the nodes. For some reason if image can't be pulled the kublet will throw ImagePullBackOff error. 

There are some possible reasons for this when kubectl is not able to pull image from mentioned registry. 

Either image or tag is not available. 

The name of the image or tag is wrong in deployment yaml file

kubectl does not have access to image registry. 

In my case there was no such issues mentioned above. The image with tag was there. I have specified the correct name in deployment yaml file and because it was a local registry, there was no need of authentication. 

So here is how I solved this issue. I set image pull policy to following value in my deployment yaml file.

imagePullPolicy: IfNotPresent

The reason it worked is, the kubectl was trying to find image in registry but it was not present because it was local registry so then it tried to find image in local repository and caches it. 

This solution worked for me because I was using local registry. If you are facing such issue try setting above value to imagePullPolicy and it may work. Hope this helps you.

Saturday, July 31, 2021

Wait for State Changes with Redux Saga

Hello,

As we know Redux saga allows us to respond to actions outside Redux store. It's kind of middleware library to handle side effects with ease. This side effect could be anything like calling APIs, doing some IO operations or anything. While working with Saga sometime it happens that we also want to detect state changes and do some actions after it. In this blog I am going to explain how you can wait or detect Redux state changes with Saga.

Let's understand with an example. For example there is an API call to get access token and as soon as you have access toke available in state you want to call some other actions like background sync etc. 


function* waitForLoginToken(selector) {

    if (yield select(selector)) return;

    while (true) {

      yield take('*');

      if (yield select(selector)) return;

    }

}

export function* postSignInAction(payload) {

    cost loginTokenSelector = state => state.auth.loginToken;

    yield call(waitForLoginToken, loginTokenSelector);

    yield put({ type: 'BACKGROUND_SYNC' });

}

function* mySaga(){

  yield takeEvery('SIGN_IN', postSignInAction);

}

As you can see in above code, we take every sign in action and call postSignInAction which will wait for state change.

We defined state selector as state.auth.loginToken. Till the time loginToken is not set in state.auth it will wait as we are using while loop to wait for state change. Once we get it in state we call next action. 

This way you can & detect state change with Redux Saga. Hope this helps you.

Saturday, July 17, 2021

React-Draft-Wysiwyg - Find Text Option

Hello,

Recently I was working on POC for rich text editor using React-Draft-Wysiwyg editor. 

There we have a requirement to add find & replace dialog box which should find the matching text from all the blocks and height it with background color. For the POC we added find text functionality. Here in this blog I will explain how to do it. 

For this I have created separate React component and add it as custom option to editor toolbar. Let's understand it step by step. 

If you want to know how to add custom option you can find reference from here.

https://jpuri.github.io/react-draft-wysiwyg/#/docs

1) Create Modal with Text input and Button

Please note I have used grommet UI library to build the POC. So text input and button was imported from Grommet.

<TextInput

    data-cy="find-text"

    autoFocus

    onChange={this.onChangeFindText}

    value={this.state.findText}

/>

<Button

    id="find"

    label="Find"

    onClick={this.onFindClick}

/>

2) Handle Find Click Event

onFindClick = () => {

  const search = this.state.findText;

  let contentState = convertToRaw(this.props.editorState.getCurrentContent());

  contentState.blocks.forEach(block => {

    const text = block.text;

    const matches = [...text.matchAll(search)];

    if(matches.length > 0) {

      matches.forEach(match =>{

        block.inlineStyleRanges.push({length: match[0].length,

          offset: match.index,

          style: "bgcolor-rgb(247,218,100)"

        })

      });

    }

  });

  let newEditorState = {

    editorState: EditorState.createWithContent(convertFromRaw({blocks: contentState.blocks,entityMap: {}})),

    contentState: null

  }

  this.props.onChange(EditorState.createWithContent(convertFromRaw({blocks: contentState.blocks,entityMap: {}})));

}

In above code we are getting search text from the state and matching it with texts of all custom blocks. Where ever it matches we are setting inline styles in blocks with yellow color background. and then setting state of editor again with new blocks. 

Hope this helps you.